Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.2k views
in Technique[技术] by (71.8m points)

typescript - TS2339 - 'Property doesn't exist on type' error in an apparently valid TS file

I have the following type declarations:

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

Since Main is equivalent to {r: string, a: string} | {r: string, b: string}, this works:

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

No surprises here. However, this throws the following error:

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' */
}

I do understand that .a doesn't exist on Root & B, but it exists on Root & A, so it must exists on (Root & A) | (Root & B) which is equivalent to Main, right?

Is it a bug, or am I missing something?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are right about Main being equivalent to (Root & A) | (Root & B) you are wrong about the interpretation of union types (|). A union type means you can assign either type in the union to main ( so either (Root & A) or (Root & B)), but you can only access common properties of the union members. In this case the common member is only r. Since main ca be either (Root & A) or (Root & B), a might not exist on main, so typescript prevents such an access.

To use the members that only exist on one type in the union you need a type guard. In this case an in type-guard will work best:

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

You can read more about type guards here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...