为什么详尽检查对联合类型的作用不同?
Why do exhaustiveness checks work differently for union types?
我正在使用 TypeScript Deep Dive
中所述的详尽检查
与非联合类型的类型相比,联合类型的详尽性检查似乎有所不同。为什么??
例如,在下面的代码中,请注意 exhaustivenessCheck1
仅在我们断言 x.kind
为 never
时有效(在不应输入错误时不输入错误)。
然而,只有当我们断言 x
是 never
时,exhaustivenessCheck2
才会做正确的事情。
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")
当您使用类型保护时,Typescript 会缩小并集。混乱来自工会的位置。
在 Variant1
中,联合位于 kind
成员上,因此打字稿将该联合缩小到 default
分支上的 never
。这意味着 x
仍然是 Variant1
类型,并且 kind
仍然可以在 x
上访问,只是此时 kind
的类型是 never
在 Variant2
中,并集在 x
参数本身上,因此 x
是变窄的。此版本也称为以 kind
为鉴别器的可鉴别联合。由于所有 kinds
都已检查,因此 default
x
将缩小到 never
,因此访问 kind
会出错。
我正在使用 TypeScript Deep Dive
中所述的详尽检查与非联合类型的类型相比,联合类型的详尽性检查似乎有所不同。为什么??
例如,在下面的代码中,请注意 exhaustivenessCheck1
仅在我们断言 x.kind
为 never
时有效(在不应输入错误时不输入错误)。
然而,只有当我们断言 x
是 never
时,exhaustivenessCheck2
才会做正确的事情。
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")
当您使用类型保护时,Typescript 会缩小并集。混乱来自工会的位置。
在 Variant1
中,联合位于 kind
成员上,因此打字稿将该联合缩小到 default
分支上的 never
。这意味着 x
仍然是 Variant1
类型,并且 kind
仍然可以在 x
上访问,只是此时 kind
的类型是 never
在 Variant2
中,并集在 x
参数本身上,因此 x
是变窄的。此版本也称为以 kind
为鉴别器的可鉴别联合。由于所有 kinds
都已检查,因此 default
x
将缩小到 never
,因此访问 kind
会出错。