3

我有以下类型声明:

type Root = { r: string };
type A = { a: string };
type B = { b: string };
type Main = Root & (A | B);

由于Main等效于{r: string, a: string} | {r: string, b: string},因此有效:

const main: Main = {
    r: 'r',
    a: 'a'
}

这里没有惊喜。但是,这会引发以下错误:

const func : (main: Main) => void = main => {
    main.a
    /*   ^
    * [TS2339]
    * Property 'a' doesn't exist on type 'Main'.
    *   Property 'a' doesn't exist on type 'Root & B' */
}

我明白那.a不存在于 上Root & B,但它存在于 上Root & A,所以它必须存在于(Root & A) | (Root & B)等于 的上Main,对吧?

这是一个错误,还是我错过了什么?

4

2 回答 2

5

关于联合类型( )的解释,您对Main等价是正确的。联合类型意味着您可以将联合中的任一类型分配给(因此,或者),但您只能访问联合成员的公共属性。在这种情况下,公共成员只有. 由于ca 是或者,可能不存在于 上,所以 typescript 会阻止这种访问。(Root & A) | (Root & B)|main(Root & A)(Root & B)rmain(Root & A)(Root & B)amain

要使用仅存在于联合中的一种类型上的成员,您需要一个类型保护。在这种情况下,in类型保护将最有效:

const func : (main: Main) => void = main => {
    if ('a' in main) {
        main.a
    } else {
        main.b
    }
}

您可以在此处阅读有关类型保护的更多信息

于 2018-12-12T13:20:45.633 回答
2

问题是编译器此时无法确保两者.a.b可用,因为这将在运行时进行验证。一旦你创建了一个 type 的变量Main,你就会指定它是 Main 的特殊类型。所以要么Root & A要么Root & B

要确保在该函数中可以访问.a.b可访问,只需执行以下操作:

type Root = { r: string };
type AB = { a?: string, b?: string };
type Main = Root & AB;

const func = (main: Main): void => {
    if ('a' in main) {
        main.a!
    } else {
        main.b!
    }
}
于 2018-12-12T13:23:46.487 回答