Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8321adf

Browse files
committedApr 18, 2019
Relate a source type that is sufficiently covered by a target discriminated union
1 parent c3a9429 commit 8321adf

File tree

7 files changed

+1286
-70
lines changed

7 files changed

+1286
-70
lines changed
 

‎src/compiler/checker.ts

+278-70
Large diffs are not rendered by default.

‎src/compiler/core.ts

+25
Original file line numberDiff line numberDiff line change
@@ -2317,4 +2317,29 @@ namespace ts {
23172317
}
23182318
return result;
23192319
}
2320+
2321+
export function cartesianProduct<T>(arrays: readonly T[][]) {
2322+
const result: T[][] = [];
2323+
cartesianProductWorker(arrays, result, /*outer*/ undefined, 0);
2324+
return result;
2325+
}
2326+
2327+
function cartesianProductWorker<T>(arrays: readonly (readonly T[])[], result: (readonly T[])[], outer: readonly T[] | undefined, index: number) {
2328+
for (const element of arrays[index]) {
2329+
let inner: T[];
2330+
if (outer) {
2331+
inner = outer.slice();
2332+
inner.push(element);
2333+
}
2334+
else {
2335+
inner = [element];
2336+
}
2337+
if (index === arrays.length - 1) {
2338+
result.push(inner);
2339+
}
2340+
else {
2341+
cartesianProductWorker(arrays, result, inner, index + 1);
2342+
}
2343+
}
2344+
}
23202345
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts(44,5): error TS2322: Type 'S' is not assignable to type 'T'.
2+
Type 'S' is not assignable to type '{ a: 2; b: 3; }'.
3+
Types of property 'a' are incompatible.
4+
Type '0 | 2' is not assignable to type '2'.
5+
Type '0' is not assignable to type '2'.
6+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts(58,5): error TS2322: Type 'S' is not assignable to type 'T'.
7+
Property 'c' is missing in type 'S' but required in type '{ a: 2; b: 4 | 3; c: string; }'.
8+
tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts(82,5): error TS2322: Type 'S' is not assignable to type 'T'.
9+
Type 'S' is not assignable to type '{ a: 0 | 2 | 1; b: 0 | 2 | 1; c: 2; }'.
10+
Types of property 'c' are incompatible.
11+
Type '0 | 2 | 1' is not assignable to type '2'.
12+
Type '0' is not assignable to type '2'.
13+
14+
15+
==== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts (3 errors) ====
16+
// see 'typeRelatedToDiscriminatedType' in checker.ts:
17+
18+
// IteratorResult
19+
namespace Example1 {
20+
type S = { done: boolean, value: number };
21+
type T =
22+
| { done: true, value: number } // T0
23+
| { done: false, value: number }; // T1
24+
25+
declare let s: S;
26+
declare let t: T;
27+
28+
// S is assignable to T0 when S["done"] is true
29+
// S is assignable to T1 when S["done"] is false
30+
t = s;
31+
}
32+
33+
// Dropping constituents of T
34+
namespace Example2 {
35+
type S = { a: 0 | 2, b: 4 };
36+
type T = { a: 0, b: 1 | 4 } // T0
37+
| { a: 1, b: 2 } // T1
38+
| { a: 2, b: 3 | 4 }; // T2
39+
declare let s: S;
40+
declare let t: T;
41+
42+
// S is assignable to T0 when S["a"] is 0
43+
// S is assignable to T2 when S["a"] is 2
44+
t = s;
45+
}
46+
47+
// Unmatched discriminants
48+
namespace Example3 {
49+
type S = { a: 0 | 2, b: 4 };
50+
type T = { a: 0, b: 1 | 4 } // T0
51+
| { a: 1, b: 2 | 4 } // T1
52+
| { a: 2, b: 3 }; // 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 T1 when S["b"] is 4
58+
// S is *not* assignable to T2 when S["a"] is 2
59+
t = s;
60+
~
61+
!!! error TS2322: Type 'S' is not assignable to type 'T'.
62+
!!! error TS2322: Type 'S' is not assignable to type '{ a: 2; b: 3; }'.
63+
!!! error TS2322: Types of property 'a' are incompatible.
64+
!!! error TS2322: Type '0 | 2' is not assignable to type '2'.
65+
!!! error TS2322: Type '0' is not assignable to type '2'.
66+
}
67+
68+
// Unmatched non-discriminants
69+
namespace Example4 {
70+
type S = { a: 0 | 2, b: 4 };
71+
type T = { a: 0, b: 1 | 4 } // T0
72+
| { a: 1, b: 2 } // T1
73+
| { a: 2, b: 3 | 4, c: string }; // T2
74+
declare let s: S;
75+
declare let t: T;
76+
77+
// S is assignable to T0 when S["a"] is 0
78+
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
79+
t = s;
80+
~
81+
!!! error TS2322: Type 'S' is not assignable to type 'T'.
82+
!!! error TS2322: Property 'c' is missing in type 'S' but required in type '{ a: 2; b: 4 | 3; c: string; }'.
83+
!!! related TS2728 tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts:52:36: 'c' is declared here.
84+
}
85+
86+
// Maximum discriminant combinations
87+
namespace Example5 {
88+
// NOTE: MAX_DISCRIMINANT_COMBINATIONS is currently 25
89+
// 3 discriminant properties with 3 types a piece
90+
// is 27 possible combinations.
91+
type N = 0 | 1 | 2;
92+
type S = { a: N, b: N, c: N };
93+
type T = { a: 0, b: N, c: N }
94+
| { a: 1, b: N, c: N }
95+
| { a: 2, b: N, c: N }
96+
| { a: N, b: 0, c: N }
97+
| { a: N, b: 1, c: N }
98+
| { a: N, b: 2, c: N }
99+
| { a: N, b: N, c: 0 }
100+
| { a: N, b: N, c: 1 }
101+
| { a: N, b: N, c: 2 };
102+
declare let s: S;
103+
declare let t: T;
104+
105+
// S *should* be assignable but the number of
106+
// combinations is too complex.
107+
t = s;
108+
~
109+
!!! error TS2322: Type 'S' is not assignable to type 'T'.
110+
!!! error TS2322: Type 'S' is not assignable to type '{ a: 0 | 2 | 1; b: 0 | 2 | 1; c: 2; }'.
111+
!!! error TS2322: Types of property 'c' are incompatible.
112+
!!! error TS2322: Type '0 | 2 | 1' is not assignable to type '2'.
113+
!!! error TS2322: Type '0' is not assignable to type '2'.
114+
}
115+
116+
// https://github.com/Microsoft/TypeScript/issues/14865
117+
namespace Example6 {
118+
type Style1 = {
119+
type: "A";
120+
data: string;
121+
} | {
122+
type: "B";
123+
data: string;
124+
};
125+
126+
type Style2 = {
127+
type: "A" | "B";
128+
data: string;
129+
}
130+
131+
const a: Style2 = { type: "A", data: "whatevs" };
132+
let b: Style1;
133+
a.type; // "A" | "B"
134+
b.type; // "A" | "B"
135+
b = a; // should be assignable
136+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
//// [assignmentCompatWithDiscriminatedUnion.ts]
2+
// see 'typeRelatedToDiscriminatedType' in checker.ts:
3+
4+
// IteratorResult
5+
namespace Example1 {
6+
type S = { done: boolean, value: number };
7+
type T =
8+
| { done: true, value: number } // T0
9+
| { done: false, value: number }; // T1
10+
11+
declare let s: S;
12+
declare let t: T;
13+
14+
// S is assignable to T0 when S["done"] is true
15+
// S is assignable to T1 when S["done"] is false
16+
t = s;
17+
}
18+
19+
// Dropping constituents of T
20+
namespace Example2 {
21+
type S = { a: 0 | 2, b: 4 };
22+
type T = { a: 0, b: 1 | 4 } // T0
23+
| { a: 1, b: 2 } // T1
24+
| { a: 2, b: 3 | 4 }; // T2
25+
declare let s: S;
26+
declare let t: T;
27+
28+
// S is assignable to T0 when S["a"] is 0
29+
// S is assignable to T2 when S["a"] is 2
30+
t = s;
31+
}
32+
33+
// Unmatched discriminants
34+
namespace Example3 {
35+
type S = { a: 0 | 2, b: 4 };
36+
type T = { a: 0, b: 1 | 4 } // T0
37+
| { a: 1, b: 2 | 4 } // T1
38+
| { a: 2, b: 3 }; // T2
39+
declare let s: S;
40+
declare let t: T;
41+
42+
// S is assignable to T0 when S["a"] is 0
43+
// S is *not* assignable to T1 when S["b"] is 4
44+
// S is *not* assignable to T2 when S["a"] is 2
45+
t = s;
46+
}
47+
48+
// Unmatched non-discriminants
49+
namespace Example4 {
50+
type S = { a: 0 | 2, b: 4 };
51+
type T = { a: 0, b: 1 | 4 } // T0
52+
| { a: 1, b: 2 } // T1
53+
| { a: 2, b: 3 | 4, c: string }; // T2
54+
declare let s: S;
55+
declare let t: T;
56+
57+
// S is assignable to T0 when S["a"] is 0
58+
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
59+
t = s;
60+
}
61+
62+
// Maximum discriminant combinations
63+
namespace Example5 {
64+
// NOTE: MAX_DISCRIMINANT_COMBINATIONS is currently 25
65+
// 3 discriminant properties with 3 types a piece
66+
// is 27 possible combinations.
67+
type N = 0 | 1 | 2;
68+
type S = { a: N, b: N, c: N };
69+
type T = { a: 0, b: N, c: N }
70+
| { a: 1, b: N, c: N }
71+
| { a: 2, b: N, c: N }
72+
| { a: N, b: 0, c: N }
73+
| { a: N, b: 1, c: N }
74+
| { a: N, b: 2, c: N }
75+
| { a: N, b: N, c: 0 }
76+
| { a: N, b: N, c: 1 }
77+
| { a: N, b: N, c: 2 };
78+
declare let s: S;
79+
declare let t: T;
80+
81+
// S *should* be assignable but the number of
82+
// combinations is too complex.
83+
t = s;
84+
}
85+
86+
// https://github.com/Microsoft/TypeScript/issues/14865
87+
namespace Example6 {
88+
type Style1 = {
89+
type: "A";
90+
data: string;
91+
} | {
92+
type: "B";
93+
data: string;
94+
};
95+
96+
type Style2 = {
97+
type: "A" | "B";
98+
data: string;
99+
}
100+
101+
const a: Style2 = { type: "A", data: "whatevs" };
102+
let b: Style1;
103+
a.type; // "A" | "B"
104+
b.type; // "A" | "B"
105+
b = a; // should be assignable
106+
}
107+
108+
//// [assignmentCompatWithDiscriminatedUnion.js]
109+
// see 'typeRelatedToDiscriminatedType' in checker.ts:
110+
// IteratorResult
111+
var Example1;
112+
(function (Example1) {
113+
// S is assignable to T0 when S["done"] is true
114+
// S is assignable to T1 when S["done"] is false
115+
t = s;
116+
})(Example1 || (Example1 = {}));
117+
// Dropping constituents of T
118+
var Example2;
119+
(function (Example2) {
120+
// S is assignable to T0 when S["a"] is 0
121+
// S is assignable to T2 when S["a"] is 2
122+
t = s;
123+
})(Example2 || (Example2 = {}));
124+
// Unmatched discriminants
125+
var Example3;
126+
(function (Example3) {
127+
// S is assignable to T0 when S["a"] is 0
128+
// S is *not* assignable to T1 when S["b"] is 4
129+
// S is *not* assignable to T2 when S["a"] is 2
130+
t = s;
131+
})(Example3 || (Example3 = {}));
132+
// Unmatched non-discriminants
133+
var Example4;
134+
(function (Example4) {
135+
// S is assignable to T0 when S["a"] is 0
136+
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
137+
t = s;
138+
})(Example4 || (Example4 = {}));
139+
// Maximum discriminant combinations
140+
var Example5;
141+
(function (Example5) {
142+
// S *should* be assignable but the number of
143+
// combinations is too complex.
144+
t = s;
145+
})(Example5 || (Example5 = {}));
146+
// https://github.com/Microsoft/TypeScript/issues/14865
147+
var Example6;
148+
(function (Example6) {
149+
var a = { type: "A", data: "whatevs" };
150+
var b;
151+
a.type; // "A" | "B"
152+
b.type; // "A" | "B"
153+
b = a; // should be assignable
154+
})(Example6 || (Example6 = {}));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
=== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts ===
2+
// see 'typeRelatedToDiscriminatedType' in checker.ts:
3+
4+
// IteratorResult
5+
namespace Example1 {
6+
>Example1 : Symbol(Example1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 0, 0))
7+
8+
type S = { done: boolean, value: number };
9+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 3, 20))
10+
>done : Symbol(done, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 14))
11+
>value : Symbol(value, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 29))
12+
13+
type T =
14+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 46))
15+
16+
| { done: true, value: number } // T0
17+
>done : Symbol(done, Decl(assignmentCompatWithDiscriminatedUnion.ts, 6, 11))
18+
>value : Symbol(value, Decl(assignmentCompatWithDiscriminatedUnion.ts, 6, 23))
19+
20+
| { done: false, value: number }; // T1
21+
>done : Symbol(done, Decl(assignmentCompatWithDiscriminatedUnion.ts, 7, 11))
22+
>value : Symbol(value, Decl(assignmentCompatWithDiscriminatedUnion.ts, 7, 24))
23+
24+
declare let s: S;
25+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 9, 15))
26+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 3, 20))
27+
28+
declare let t: T;
29+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 10, 15))
30+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 4, 46))
31+
32+
// S is assignable to T0 when S["done"] is true
33+
// S is assignable to T1 when S["done"] is false
34+
t = s;
35+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 10, 15))
36+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 9, 15))
37+
}
38+
39+
// Dropping constituents of T
40+
namespace Example2 {
41+
>Example2 : Symbol(Example2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 15, 1))
42+
43+
type S = { a: 0 | 2, b: 4 };
44+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 18, 20))
45+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 14))
46+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 24))
47+
48+
type T = { a: 0, b: 1 | 4 } // T0
49+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 32))
50+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 20, 14))
51+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 20, 20))
52+
53+
| { a: 1, b: 2 } // T1
54+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 21, 14))
55+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 21, 20))
56+
57+
| { a: 2, b: 3 | 4 }; // T2
58+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 22, 14))
59+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 22, 20))
60+
61+
declare let s: S;
62+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 23, 15))
63+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 18, 20))
64+
65+
declare let t: T;
66+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 24, 15))
67+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 19, 32))
68+
69+
// S is assignable to T0 when S["a"] is 0
70+
// S is assignable to T2 when S["a"] is 2
71+
t = s;
72+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 24, 15))
73+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 23, 15))
74+
}
75+
76+
// Unmatched discriminants
77+
namespace Example3 {
78+
>Example3 : Symbol(Example3, Decl(assignmentCompatWithDiscriminatedUnion.ts, 29, 1))
79+
80+
type S = { a: 0 | 2, b: 4 };
81+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 32, 20))
82+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 14))
83+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 24))
84+
85+
type T = { a: 0, b: 1 | 4 } // T0
86+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 32))
87+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 34, 14))
88+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 34, 20))
89+
90+
| { a: 1, b: 2 | 4 } // T1
91+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 35, 14))
92+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 35, 20))
93+
94+
| { a: 2, b: 3 }; // T2
95+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 36, 14))
96+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 36, 20))
97+
98+
declare let s: S;
99+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 37, 15))
100+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 32, 20))
101+
102+
declare let t: T;
103+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 38, 15))
104+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 33, 32))
105+
106+
// S is assignable to T0 when S["a"] is 0
107+
// S is *not* assignable to T1 when S["b"] is 4
108+
// S is *not* assignable to T2 when S["a"] is 2
109+
t = s;
110+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 38, 15))
111+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 37, 15))
112+
}
113+
114+
// Unmatched non-discriminants
115+
namespace Example4 {
116+
>Example4 : Symbol(Example4, Decl(assignmentCompatWithDiscriminatedUnion.ts, 44, 1))
117+
118+
type S = { a: 0 | 2, b: 4 };
119+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 47, 20))
120+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 14))
121+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 24))
122+
123+
type T = { a: 0, b: 1 | 4 } // T0
124+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 32))
125+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 49, 14))
126+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 49, 20))
127+
128+
| { a: 1, b: 2 } // T1
129+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 50, 14))
130+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 50, 20))
131+
132+
| { a: 2, b: 3 | 4, c: string }; // T2
133+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 51, 14))
134+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 51, 20))
135+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 51, 34))
136+
137+
declare let s: S;
138+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 52, 15))
139+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 47, 20))
140+
141+
declare let t: T;
142+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 53, 15))
143+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 48, 32))
144+
145+
// S is assignable to T0 when S["a"] is 0
146+
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
147+
t = s;
148+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 53, 15))
149+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 52, 15))
150+
}
151+
152+
// Maximum discriminant combinations
153+
namespace Example5 {
154+
>Example5 : Symbol(Example5, Decl(assignmentCompatWithDiscriminatedUnion.ts, 58, 1))
155+
156+
// NOTE: MAX_DISCRIMINANT_COMBINATIONS is currently 25
157+
// 3 discriminant properties with 3 types a piece
158+
// is 27 possible combinations.
159+
type N = 0 | 1 | 2;
160+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
161+
162+
type S = { a: N, b: N, c: N };
163+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 65, 23))
164+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 14))
165+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
166+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 20))
167+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
168+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 26))
169+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
170+
171+
type T = { a: 0, b: N, c: N }
172+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 34))
173+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 67, 14))
174+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 67, 20))
175+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
176+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 67, 26))
177+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
178+
179+
| { a: 1, b: N, c: N }
180+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 68, 14))
181+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 68, 20))
182+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
183+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 68, 26))
184+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
185+
186+
| { a: 2, b: N, c: N }
187+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 69, 14))
188+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 69, 20))
189+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
190+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 69, 26))
191+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
192+
193+
| { a: N, b: 0, c: N }
194+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 70, 14))
195+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
196+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 70, 20))
197+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 70, 26))
198+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
199+
200+
| { a: N, b: 1, c: N }
201+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 71, 14))
202+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
203+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 71, 20))
204+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 71, 26))
205+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
206+
207+
| { a: N, b: 2, c: N }
208+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 72, 14))
209+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
210+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 72, 20))
211+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 72, 26))
212+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
213+
214+
| { a: N, b: N, c: 0 }
215+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 73, 14))
216+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
217+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 73, 20))
218+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
219+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 73, 26))
220+
221+
| { a: N, b: N, c: 1 }
222+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 74, 14))
223+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
224+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 74, 20))
225+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
226+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 74, 26))
227+
228+
| { a: N, b: N, c: 2 };
229+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 75, 14))
230+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
231+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 75, 20))
232+
>N : Symbol(N, Decl(assignmentCompatWithDiscriminatedUnion.ts, 61, 20))
233+
>c : Symbol(c, Decl(assignmentCompatWithDiscriminatedUnion.ts, 75, 26))
234+
235+
declare let s: S;
236+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 76, 15))
237+
>S : Symbol(S, Decl(assignmentCompatWithDiscriminatedUnion.ts, 65, 23))
238+
239+
declare let t: T;
240+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 77, 15))
241+
>T : Symbol(T, Decl(assignmentCompatWithDiscriminatedUnion.ts, 66, 34))
242+
243+
// S *should* be assignable but the number of
244+
// combinations is too complex.
245+
t = s;
246+
>t : Symbol(t, Decl(assignmentCompatWithDiscriminatedUnion.ts, 77, 15))
247+
>s : Symbol(s, Decl(assignmentCompatWithDiscriminatedUnion.ts, 76, 15))
248+
}
249+
250+
// https://github.com/Microsoft/TypeScript/issues/14865
251+
namespace Example6 {
252+
>Example6 : Symbol(Example6, Decl(assignmentCompatWithDiscriminatedUnion.ts, 82, 1))
253+
254+
type Style1 = {
255+
>Style1 : Symbol(Style1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 85, 20))
256+
257+
type: "A";
258+
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 86, 19))
259+
260+
data: string;
261+
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 87, 18))
262+
263+
} | {
264+
type: "B";
265+
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 89, 9))
266+
267+
data: string;
268+
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 90, 18))
269+
270+
};
271+
272+
type Style2 = {
273+
>Style2 : Symbol(Style2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 92, 6))
274+
275+
type: "A" | "B";
276+
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 94, 19))
277+
278+
data: string;
279+
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 95, 24))
280+
}
281+
282+
const a: Style2 = { type: "A", data: "whatevs" };
283+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 9))
284+
>Style2 : Symbol(Style2, Decl(assignmentCompatWithDiscriminatedUnion.ts, 92, 6))
285+
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 23))
286+
>data : Symbol(data, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 34))
287+
288+
let b: Style1;
289+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 100, 7))
290+
>Style1 : Symbol(Style1, Decl(assignmentCompatWithDiscriminatedUnion.ts, 85, 20))
291+
292+
a.type; // "A" | "B"
293+
>a.type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 94, 19))
294+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 9))
295+
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 94, 19))
296+
297+
b.type; // "A" | "B"
298+
>b.type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 86, 19), Decl(assignmentCompatWithDiscriminatedUnion.ts, 89, 9))
299+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 100, 7))
300+
>type : Symbol(type, Decl(assignmentCompatWithDiscriminatedUnion.ts, 86, 19), Decl(assignmentCompatWithDiscriminatedUnion.ts, 89, 9))
301+
302+
b = a; // should be assignable
303+
>b : Symbol(b, Decl(assignmentCompatWithDiscriminatedUnion.ts, 100, 7))
304+
>a : Symbol(a, Decl(assignmentCompatWithDiscriminatedUnion.ts, 99, 9))
305+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
=== tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts ===
2+
// see 'typeRelatedToDiscriminatedType' in checker.ts:
3+
4+
// IteratorResult
5+
namespace Example1 {
6+
>Example1 : typeof Example1
7+
8+
type S = { done: boolean, value: number };
9+
>S : S
10+
>done : boolean
11+
>value : number
12+
13+
type T =
14+
>T : T
15+
16+
| { done: true, value: number } // T0
17+
>done : true
18+
>true : true
19+
>value : number
20+
21+
| { done: false, value: number }; // T1
22+
>done : false
23+
>false : false
24+
>value : number
25+
26+
declare let s: S;
27+
>s : S
28+
29+
declare let t: T;
30+
>t : T
31+
32+
// S is assignable to T0 when S["done"] is true
33+
// S is assignable to T1 when S["done"] is false
34+
t = s;
35+
>t = s : S
36+
>t : T
37+
>s : S
38+
}
39+
40+
// Dropping constituents of T
41+
namespace Example2 {
42+
>Example2 : typeof Example2
43+
44+
type S = { a: 0 | 2, b: 4 };
45+
>S : S
46+
>a : 0 | 2
47+
>b : 4
48+
49+
type T = { a: 0, b: 1 | 4 } // T0
50+
>T : T
51+
>a : 0
52+
>b : 4 | 1
53+
54+
| { a: 1, b: 2 } // T1
55+
>a : 1
56+
>b : 2
57+
58+
| { a: 2, b: 3 | 4 }; // T2
59+
>a : 2
60+
>b : 4 | 3
61+
62+
declare let s: S;
63+
>s : S
64+
65+
declare let t: T;
66+
>t : T
67+
68+
// S is assignable to T0 when S["a"] is 0
69+
// S is assignable to T2 when S["a"] is 2
70+
t = s;
71+
>t = s : S
72+
>t : T
73+
>s : S
74+
}
75+
76+
// Unmatched discriminants
77+
namespace Example3 {
78+
>Example3 : typeof Example3
79+
80+
type S = { a: 0 | 2, b: 4 };
81+
>S : S
82+
>a : 0 | 2
83+
>b : 4
84+
85+
type T = { a: 0, b: 1 | 4 } // T0
86+
>T : T
87+
>a : 0
88+
>b : 4 | 1
89+
90+
| { a: 1, b: 2 | 4 } // T1
91+
>a : 1
92+
>b : 2 | 4
93+
94+
| { a: 2, b: 3 }; // T2
95+
>a : 2
96+
>b : 3
97+
98+
declare let s: S;
99+
>s : S
100+
101+
declare let t: T;
102+
>t : T
103+
104+
// S is assignable to T0 when S["a"] is 0
105+
// S is *not* assignable to T1 when S["b"] is 4
106+
// S is *not* assignable to T2 when S["a"] is 2
107+
t = s;
108+
>t = s : S
109+
>t : T
110+
>s : S
111+
}
112+
113+
// Unmatched non-discriminants
114+
namespace Example4 {
115+
>Example4 : typeof Example4
116+
117+
type S = { a: 0 | 2, b: 4 };
118+
>S : S
119+
>a : 0 | 2
120+
>b : 4
121+
122+
type T = { a: 0, b: 1 | 4 } // T0
123+
>T : T
124+
>a : 0
125+
>b : 4 | 1
126+
127+
| { a: 1, b: 2 } // T1
128+
>a : 1
129+
>b : 2
130+
131+
| { a: 2, b: 3 | 4, c: string }; // T2
132+
>a : 2
133+
>b : 4 | 3
134+
>c : string
135+
136+
declare let s: S;
137+
>s : S
138+
139+
declare let t: T;
140+
>t : T
141+
142+
// S is assignable to T0 when S["a"] is 0
143+
// S is *not* assignable to T2 when S["a"] is 2 as S is missing "c"
144+
t = s;
145+
>t = s : S
146+
>t : T
147+
>s : S
148+
}
149+
150+
// Maximum discriminant combinations
151+
namespace Example5 {
152+
>Example5 : typeof Example5
153+
154+
// NOTE: MAX_DISCRIMINANT_COMBINATIONS is currently 25
155+
// 3 discriminant properties with 3 types a piece
156+
// is 27 possible combinations.
157+
type N = 0 | 1 | 2;
158+
>N : 0 | 2 | 1
159+
160+
type S = { a: N, b: N, c: N };
161+
>S : S
162+
>a : 0 | 2 | 1
163+
>b : 0 | 2 | 1
164+
>c : 0 | 2 | 1
165+
166+
type T = { a: 0, b: N, c: N }
167+
>T : T
168+
>a : 0
169+
>b : 0 | 2 | 1
170+
>c : 0 | 2 | 1
171+
172+
| { a: 1, b: N, c: N }
173+
>a : 1
174+
>b : 0 | 2 | 1
175+
>c : 0 | 2 | 1
176+
177+
| { a: 2, b: N, c: N }
178+
>a : 2
179+
>b : 0 | 2 | 1
180+
>c : 0 | 2 | 1
181+
182+
| { a: N, b: 0, c: N }
183+
>a : 0 | 2 | 1
184+
>b : 0
185+
>c : 0 | 2 | 1
186+
187+
| { a: N, b: 1, c: N }
188+
>a : 0 | 2 | 1
189+
>b : 1
190+
>c : 0 | 2 | 1
191+
192+
| { a: N, b: 2, c: N }
193+
>a : 0 | 2 | 1
194+
>b : 2
195+
>c : 0 | 2 | 1
196+
197+
| { a: N, b: N, c: 0 }
198+
>a : 0 | 2 | 1
199+
>b : 0 | 2 | 1
200+
>c : 0
201+
202+
| { a: N, b: N, c: 1 }
203+
>a : 0 | 2 | 1
204+
>b : 0 | 2 | 1
205+
>c : 1
206+
207+
| { a: N, b: N, c: 2 };
208+
>a : 0 | 2 | 1
209+
>b : 0 | 2 | 1
210+
>c : 2
211+
212+
declare let s: S;
213+
>s : S
214+
215+
declare let t: T;
216+
>t : T
217+
218+
// S *should* be assignable but the number of
219+
// combinations is too complex.
220+
t = s;
221+
>t = s : S
222+
>t : T
223+
>s : S
224+
}
225+
226+
// https://github.com/Microsoft/TypeScript/issues/14865
227+
namespace Example6 {
228+
>Example6 : typeof Example6
229+
230+
type Style1 = {
231+
>Style1 : Style1
232+
233+
type: "A";
234+
>type : "A"
235+
236+
data: string;
237+
>data : string
238+
239+
} | {
240+
type: "B";
241+
>type : "B"
242+
243+
data: string;
244+
>data : string
245+
246+
};
247+
248+
type Style2 = {
249+
>Style2 : Style2
250+
251+
type: "A" | "B";
252+
>type : "A" | "B"
253+
254+
data: string;
255+
>data : string
256+
}
257+
258+
const a: Style2 = { type: "A", data: "whatevs" };
259+
>a : Style2
260+
>{ type: "A", data: "whatevs" } : { type: "A"; data: string; }
261+
>type : "A"
262+
>"A" : "A"
263+
>data : string
264+
>"whatevs" : "whatevs"
265+
266+
let b: Style1;
267+
>b : Style1
268+
269+
a.type; // "A" | "B"
270+
>a.type : "A" | "B"
271+
>a : Style2
272+
>type : "A" | "B"
273+
274+
b.type; // "A" | "B"
275+
>b.type : "A" | "B"
276+
>b : Style1
277+
>type : "A" | "B"
278+
279+
b = a; // should be assignable
280+
>b = a : Style2
281+
>b : Style1
282+
>a : Style2
283+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// see 'typeRelatedToDiscriminatedType' in checker.ts:
2+
3+
// IteratorResult
4+
namespace 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
19+
namespace 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
33+
namespace 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
48+
namespace 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
62+
namespace Example5 {
63+
// NOTE: MAX_DISCRIMINANT_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
86+
namespace Example6 {
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+
}

0 commit comments

Comments
 (0)
Please sign in to comment.