我正在使用TypeScript Deep Dive
中所述的详尽检查与非联合类型的类型相比,联合类型的穷举性检查的工作方式似乎有所不同。为什么?
例如,在下面的代码中,请注意,只有在我们断言exhaustivenessCheck1
为x.kind
的情况下,never
才有效(不应该输入error)。
但是,exhaustivenessCheck2
仅在我们断言x
是never
时才做正确的事。
type Variant1 = {
kind: 1 | 2
}
type Variant2 = {
kind: 1
} | {
kind: 2
}
const x: Variant1 = { kind: 1 };
function exhaustivenessCheck1(x: Variant1) {
switch (x.kind) {
case 1:
case 2:
break;
default:
const _x: never = x.kind; // OK
const _y: never = x; // Error
}
}
function exhaustivenessCheck2(x: Variant2) {
switch (x.kind) {
case 1:
break;
case 2:
break;
default:
const _x: never = x.kind; // Error
const _y: never = x; // OK
}
}
TypeScript Playground link (be sure to enable "strict null checks")
答案 0 :(得分:2)
当您使用类型防护时,Typescript会缩小联合。混乱源自工会的所在地。
在Variant1
中,该联合位于kind
成员上,因此打字稿将该联合的范围缩小到never
分支上的default
。这意味着x
仍为Variant1
类型,并且kind
仍可在x
上访问,只是此时kind
的类型为{{1 }}
在never
中,并集位于Variant2
参数本身上,因此x
是缩小的内容。此版本也称为歧视联合,其中x
为歧视者。由于已检查所有kind
,因此kinds
上的default
的范围已缩小到x
,因此访问never
成为错误。