当没有类型注释时,Typescript 抱怨受歧视的联合类型

Typescript complains about discriminated union types when there is no type annotation

在我看来,在没有任何类型注释的情况下,打字稿无法识别可区分的联合类型。我错过了什么吗?这有什么原因吗?

export type Stuff = AType | BType

export type AType = { status: Kind.A; name: string }

export type BType = { status: Kind.B; quantity: number }

export enum Kind {
  A,
  B,
}

function PlayWithStuff(stuff: Stuff) {
  console.log('some stuff', stuff)
}

const stuff = {
  status: Kind.B,
  quantity: 2,
}

PlayWithStuff(stuff)
//            ^^^^^
// Argument of type '{ status: Kind; quantity: number; }' is not assignable to parameter of type 'Stuff'.
//   Type '{ status: Kind; quantity: number; }' is not assignable to type 'BType'.
//     Types of property 'status' are incompatible.
//       Type 'Kind' is not assignable to type 'Kind.B'.

const secondStuff: Stuff = {
  status: Kind.B,
  quantity: 2,
}

PlayWithStuff(secondStuff)
// OK, the type annotation on `secondStuff` fixes the problem

当初始化对象字面量时,Typescript 将推断 属性 类型,但不是常量,因为它们不是只读的。

因此 stuff 的类型将是 { status: Kind, quantity: number },因为您稍后可以将其更改为:

const stuff = {
    status: Kind.B,
    quantity: 2,
};

stuff.status = Kind.A;

所以现在它不能分配给 BType(也不能分配给 AType)。

您可以使用 as const:

const stuff = {
    status: Kind.B,
    quantity: 2,
} as const;

现在类型被推断为 { readonly status: Kind.B, readonly quantity: 2},它始终可分配给 BType。

或者你可以做你所做的,只是给它类型注释:

const stuff: BType = {
    status: Kind.B,
    quantity: 2,
};

stuff.status = Kind.A; // Errors