为什么穷举检查对于工会类型有不同的作用?

时间:2019-01-30 22:38:20

标签: typescript variant discriminated-union

我正在使用TypeScript Deep Dive

中所述的详尽检查

与非联合类型的类型相比,联合类型的穷举性检查的工作方式似乎有所不同。为什么?

例如,在下面的代码中,请注意,只有在我们断言exhaustivenessCheck1x.kind的情况下,never才有效(不应该输入error)。

但是,exhaustivenessCheck2仅在我们断言xnever时才做正确的事。

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")

1 个答案:

答案 0 :(得分:2)

当您使用类型防护时,Typescript会缩小联合。混乱源自工会的所在地。

Variant1中,该联合位于kind成员上,因此打字稿将该联合的范围缩小到never分支上的default。这意味着x仍为Variant1类型,并且kind仍可在x上访问,只是此时kind的类型为{{1 }}

never中,并集位于Variant2参数本身上,因此x是缩小的内容。此版本也称为歧视联合,其中x为歧视者。由于已检查所有kind,因此kinds上的default的范围已缩小到x,因此访问never成为错误。