• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// see 'typeRelatedToDiscriminatedType' in checker.ts:
2
3// IteratorResult
4namespace Example1 {
5    type S = { done: boolean, value: number };
6    type T =
7        | { done: true, value: number }     // T0
8        | { done: false, value: number };   // T1
9
10    declare let s: S;
11    declare let t: T;
12
13    // S is assignable to T0 when S["done"] is true
14    // S is assignable to T1 when S["done"] is false
15    t = s;
16}
17
18// Dropping constituents of T
19namespace Example2 {
20    type S = { a: 0 | 2, b: 4 };
21    type T = { a: 0,     b: 1 | 4 }     // T0
22           | { a: 1,     b: 2 }         // T1
23           | { a: 2,     b: 3 | 4 };    // T2
24    declare let s: S;
25    declare let t: T;
26
27    // S is assignable to T0 when S["a"] is 0
28    // S is assignable to T2 when S["a"] is 2
29    t = s;
30}
31
32// Unmatched discriminants
33namespace Example3 {
34    type S = { a: 0 | 2, b: 4 };
35    type T = { a: 0,     b: 1 | 4 }     // T0
36           | { a: 1,     b: 2 | 4 }     // T1
37           | { a: 2,     b: 3 };        // T2
38    declare let s: S;
39    declare let t: T;
40
41    // S is assignable to T0 when S["a"] is 0
42    // S is *not* assignable to T1 when S["b"] is 4
43    // S is *not* assignable to T2 when S["a"] is 2
44    t = s;
45}
46
47// Unmatched non-discriminants
48namespace Example4 {
49    type S = { a: 0 | 2, b: 4 };
50    type T = { a: 0,     b: 1 | 4 }             // T0
51           | { a: 1,     b: 2 }                 // T1
52           | { a: 2,     b: 3 | 4, c: string }; // T2
53    declare let s: S;
54    declare let t: T;
55
56    // S is assignable to T0 when S["a"] is 0
57    // S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
58    t = s;
59}
60
61// Maximum discriminant combinations
62namespace Example5 {
63    // NOTE: The maximum number of discriminant type combinations is currently 25.
64    //       3 discriminant properties with 3 types a piece
65    //       is 27 possible combinations.
66    type N = 0 | 1 | 2;
67    type S = { a: N, b: N, c: N };
68    type T = { a: 0, b: N, c: N }
69           | { a: 1, b: N, c: N }
70           | { a: 2, b: N, c: N }
71           | { a: N, b: 0, c: N }
72           | { a: N, b: 1, c: N }
73           | { a: N, b: 2, c: N }
74           | { a: N, b: N, c: 0 }
75           | { a: N, b: N, c: 1 }
76           | { a: N, b: N, c: 2 };
77    declare let s: S;
78    declare let t: T;
79
80    // S *should* be assignable but the number of
81    // combinations is too complex.
82    t = s;
83}
84
85// https://github.com/Microsoft/TypeScript/issues/14865
86namespace GH14865 {
87    type Style1 = {
88        type: "A";
89        data: string;
90    } | {
91        type: "B";
92        data: string;
93    };
94
95    type Style2 = {
96        type: "A" | "B";
97        data: string;
98    }
99
100    const a: Style2 = { type: "A", data: "whatevs" };
101    let b: Style1;
102    a.type; // "A" | "B"
103    b.type; // "A" | "B"
104    b = a; // should be assignable
105}
106
107// https://github.com/Microsoft/TypeScript/issues/30170
108namespace GH30170 {
109    interface Blue {
110        color: 'blue'
111    }
112    interface Yellow {
113        color?: 'yellow',
114    }
115    function draw(val: Blue | Yellow) { }
116
117    function drawWithColor(currentColor: 'blue' | 'yellow' | undefined) {
118        return draw({ color: currentColor });
119    }
120}
121
122// https://github.com/Microsoft/TypeScript/issues/12052
123namespace GH12052 {
124    interface ILinearAxis { type: "linear"; }
125
126    interface ICategoricalAxis { type: "categorical"; }
127
128    type IAxis = ILinearAxis | ICategoricalAxis;
129    type IAxisType = "linear" | "categorical";
130
131    function getAxisType(): IAxisType {
132        if (1 == 1) {
133            return "categorical";
134        } else {
135            return "linear";
136        }
137    }
138
139    const bad: IAxis = { type: getAxisType() };
140    const good: IAxis = { type: undefined };
141    good.type = getAxisType();
142}
143
144// https://github.com/Microsoft/TypeScript/issues/18421
145namespace GH18421 {
146    interface ThingTypeOne {
147        type: 'one';
148    }
149
150    interface ThingTypeTwo {
151        type: 'two';
152    }
153
154    type ThingType = 'one' | 'two';
155
156    type Thing = ThingTypeOne | ThingTypeTwo;
157
158    function makeNewThing(thingType: ThingType): Thing {
159        return {
160            type: thingType
161        };
162    }
163}
164
165// https://github.com/Microsoft/TypeScript/issues/15907
166namespace GH15907 {
167    type Action = { type: 'activate' } | { type: 'disactivate' };
168
169    function dispatchAction(action: Action): void {
170
171    }
172
173    const active = true;
174
175    dispatchAction({ type : (active? 'disactivate' : 'activate') });
176}
177
178// https://github.com/Microsoft/TypeScript/issues/20889
179namespace GH20889 {
180    interface A1 {
181        type: "A1";
182    }
183    interface A2 {
184        type: "A2";
185    }
186    type AU = A1 | A2;
187
188    function foo(obj1: AU) {
189        const obj2: AU = {
190            type: obj1.type
191        };
192    }
193}
194
195// https://github.com/microsoft/TypeScript/issues/39357
196namespace GH39357 {
197    type A = ["a", number] | ["b", number] | ["c", string];
198    type B = "a" | "b" | "c";
199    declare const b: B;
200    const a: A = b === "a" || b === "b" ? [b, 1] : ["c", ""];
201}
202