Skip to content

Commit f3d57cc

Browse files
authored
Remove undefined from source type of renaming destructuring assignment with default (#41042)
* Remove undefined from source type of destructuring assignment with renaming * add a test * add test case from original issue * add test with undefined default value * add more test cases with const declaration
1 parent 1beb103 commit f3d57cc

6 files changed

+324
-0
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33704,6 +33704,10 @@ namespace ts {
3370433704
if (target.kind === SyntaxKind.BinaryExpression && (target as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
3370533705
checkBinaryExpression(target as BinaryExpression, checkMode);
3370633706
target = (target as BinaryExpression).left;
33707+
// A default value is specified, so remove undefined from the final type.
33708+
if (strictNullChecks) {
33709+
sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined);
33710+
}
3370733711
}
3370833712
if (target.kind === SyntaxKind.ObjectLiteralExpression) {
3370933713
return checkObjectLiteralAssignment(target as ObjectLiteralExpression, sourceType, rightIsThis);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
tests/cases/compiler/destructuringAssignmentWithDefault2.ts(11,4): error TS2322: Type 'undefined' is not assignable to type 'number'.
2+
tests/cases/compiler/destructuringAssignmentWithDefault2.ts(11,4): error TS2322: Type 'number | undefined' is not assignable to type 'number'.
3+
Type 'undefined' is not assignable to type 'number'.
4+
tests/cases/compiler/destructuringAssignmentWithDefault2.ts(12,7): error TS2322: Type 'undefined' is not assignable to type 'number'.
5+
tests/cases/compiler/destructuringAssignmentWithDefault2.ts(13,7): error TS2322: Type 'undefined' is not assignable to type 'number'.
6+
7+
8+
==== tests/cases/compiler/destructuringAssignmentWithDefault2.ts (4 errors) ====
9+
const a: { x?: number; y?: number } = { };
10+
11+
let x: number;
12+
13+
// Should not error out
14+
({ x = 0 } = a);
15+
({ x: x = 0} = a);
16+
({ y: x = 0} = a);
17+
18+
// Should be error
19+
({ x = undefined } = a);
20+
~
21+
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
22+
~
23+
!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'.
24+
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
25+
({ x: x = undefined } = a);
26+
~
27+
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
28+
({ y: x = undefined } = a);
29+
~
30+
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
31+
32+
const { x: z1 } = a;
33+
const { x: z2 = 0 } = a;
34+
const { x: z3 = undefined } = a;
35+
36+
37+
declare const r: Iterator<number>;
38+
let done: boolean;
39+
let value;
40+
41+
({ done = false, value } = r.next());
42+
({ done: done = false, value } = r.next());
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//// [destructuringAssignmentWithDefault2.ts]
2+
const a: { x?: number; y?: number } = { };
3+
4+
let x: number;
5+
6+
// Should not error out
7+
({ x = 0 } = a);
8+
({ x: x = 0} = a);
9+
({ y: x = 0} = a);
10+
11+
// Should be error
12+
({ x = undefined } = a);
13+
({ x: x = undefined } = a);
14+
({ y: x = undefined } = a);
15+
16+
const { x: z1 } = a;
17+
const { x: z2 = 0 } = a;
18+
const { x: z3 = undefined } = a;
19+
20+
21+
declare const r: Iterator<number>;
22+
let done: boolean;
23+
let value;
24+
25+
({ done = false, value } = r.next());
26+
({ done: done = false, value } = r.next());
27+
28+
//// [destructuringAssignmentWithDefault2.js]
29+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
30+
var a = {};
31+
var x;
32+
// Should not error out
33+
(_a = a.x, x = _a === void 0 ? 0 : _a);
34+
(_b = a.x, x = _b === void 0 ? 0 : _b);
35+
(_c = a.y, x = _c === void 0 ? 0 : _c);
36+
// Should be error
37+
(_d = a.x, x = _d === void 0 ? undefined : _d);
38+
(_e = a.x, x = _e === void 0 ? undefined : _e);
39+
(_f = a.y, x = _f === void 0 ? undefined : _f);
40+
var z1 = a.x;
41+
var _l = a.x, z2 = _l === void 0 ? 0 : _l;
42+
var _m = a.x, z3 = _m === void 0 ? undefined : _m;
43+
var done;
44+
var value;
45+
(_g = r.next(), _h = _g.done, done = _h === void 0 ? false : _h, value = _g.value);
46+
(_j = r.next(), _k = _j.done, done = _k === void 0 ? false : _k, value = _j.value);
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
=== tests/cases/compiler/destructuringAssignmentWithDefault2.ts ===
2+
const a: { x?: number; y?: number } = { };
3+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
4+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 0, 10))
5+
>y : Symbol(y, Decl(destructuringAssignmentWithDefault2.ts, 0, 22))
6+
7+
let x: number;
8+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 2, 3))
9+
10+
// Should not error out
11+
({ x = 0 } = a);
12+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 5, 2))
13+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
14+
15+
({ x: x = 0} = a);
16+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 6, 2))
17+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 2, 3))
18+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
19+
20+
({ y: x = 0} = a);
21+
>y : Symbol(y, Decl(destructuringAssignmentWithDefault2.ts, 7, 2))
22+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 2, 3))
23+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
24+
25+
// Should be error
26+
({ x = undefined } = a);
27+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 10, 2))
28+
>undefined : Symbol(undefined)
29+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
30+
31+
({ x: x = undefined } = a);
32+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 11, 2))
33+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 2, 3))
34+
>undefined : Symbol(undefined)
35+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
36+
37+
({ y: x = undefined } = a);
38+
>y : Symbol(y, Decl(destructuringAssignmentWithDefault2.ts, 12, 2))
39+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 2, 3))
40+
>undefined : Symbol(undefined)
41+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
42+
43+
const { x: z1 } = a;
44+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 0, 10))
45+
>z1 : Symbol(z1, Decl(destructuringAssignmentWithDefault2.ts, 14, 7))
46+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
47+
48+
const { x: z2 = 0 } = a;
49+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 0, 10))
50+
>z2 : Symbol(z2, Decl(destructuringAssignmentWithDefault2.ts, 15, 7))
51+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
52+
53+
const { x: z3 = undefined } = a;
54+
>x : Symbol(x, Decl(destructuringAssignmentWithDefault2.ts, 0, 10))
55+
>z3 : Symbol(z3, Decl(destructuringAssignmentWithDefault2.ts, 16, 7))
56+
>undefined : Symbol(undefined)
57+
>a : Symbol(a, Decl(destructuringAssignmentWithDefault2.ts, 0, 5))
58+
59+
60+
declare const r: Iterator<number>;
61+
>r : Symbol(r, Decl(destructuringAssignmentWithDefault2.ts, 19, 13))
62+
>Iterator : Symbol(Iterator, Decl(lib.es2015.iterable.d.ts, --, --))
63+
64+
let done: boolean;
65+
>done : Symbol(done, Decl(destructuringAssignmentWithDefault2.ts, 20, 3))
66+
67+
let value;
68+
>value : Symbol(value, Decl(destructuringAssignmentWithDefault2.ts, 21, 3))
69+
70+
({ done = false, value } = r.next());
71+
>done : Symbol(done, Decl(destructuringAssignmentWithDefault2.ts, 23, 2))
72+
>value : Symbol(value, Decl(destructuringAssignmentWithDefault2.ts, 23, 16))
73+
>r.next : Symbol(Iterator.next, Decl(lib.es2015.iterable.d.ts, --, --))
74+
>r : Symbol(r, Decl(destructuringAssignmentWithDefault2.ts, 19, 13))
75+
>next : Symbol(Iterator.next, Decl(lib.es2015.iterable.d.ts, --, --))
76+
77+
({ done: done = false, value } = r.next());
78+
>done : Symbol(done, Decl(destructuringAssignmentWithDefault2.ts, 24, 2))
79+
>done : Symbol(done, Decl(destructuringAssignmentWithDefault2.ts, 20, 3))
80+
>value : Symbol(value, Decl(destructuringAssignmentWithDefault2.ts, 24, 22))
81+
>r.next : Symbol(Iterator.next, Decl(lib.es2015.iterable.d.ts, --, --))
82+
>r : Symbol(r, Decl(destructuringAssignmentWithDefault2.ts, 19, 13))
83+
>next : Symbol(Iterator.next, Decl(lib.es2015.iterable.d.ts, --, --))
84+
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
=== tests/cases/compiler/destructuringAssignmentWithDefault2.ts ===
2+
const a: { x?: number; y?: number } = { };
3+
>a : { x?: number | undefined; y?: number | undefined; }
4+
>x : number | undefined
5+
>y : number | undefined
6+
>{ } : {}
7+
8+
let x: number;
9+
>x : number
10+
11+
// Should not error out
12+
({ x = 0 } = a);
13+
>({ x = 0 } = a) : { x?: number | undefined; y?: number | undefined; }
14+
>{ x = 0 } = a : { x?: number | undefined; y?: number | undefined; }
15+
>{ x = 0 } : { x?: number; }
16+
>x : number
17+
>0 : 0
18+
>a : { x?: number | undefined; y?: number | undefined; }
19+
20+
({ x: x = 0} = a);
21+
>({ x: x = 0} = a) : { x?: number | undefined; y?: number | undefined; }
22+
>{ x: x = 0} = a : { x?: number | undefined; y?: number | undefined; }
23+
>{ x: x = 0} : { x?: number; }
24+
>x : number
25+
>x = 0 : 0
26+
>x : number
27+
>0 : 0
28+
>a : { x?: number | undefined; y?: number | undefined; }
29+
30+
({ y: x = 0} = a);
31+
>({ y: x = 0} = a) : { x?: number | undefined; y?: number | undefined; }
32+
>{ y: x = 0} = a : { x?: number | undefined; y?: number | undefined; }
33+
>{ y: x = 0} : { y?: number; }
34+
>y : number
35+
>x = 0 : 0
36+
>x : number
37+
>0 : 0
38+
>a : { x?: number | undefined; y?: number | undefined; }
39+
40+
// Should be error
41+
({ x = undefined } = a);
42+
>({ x = undefined } = a) : { x?: number | undefined; y?: number | undefined; }
43+
>{ x = undefined } = a : { x?: number | undefined; y?: number | undefined; }
44+
>{ x = undefined } : { x?: number; }
45+
>x : number
46+
>undefined : undefined
47+
>a : { x?: number | undefined; y?: number | undefined; }
48+
49+
({ x: x = undefined } = a);
50+
>({ x: x = undefined } = a) : { x?: number | undefined; y?: number | undefined; }
51+
>{ x: x = undefined } = a : { x?: number | undefined; y?: number | undefined; }
52+
>{ x: x = undefined } : { x?: undefined; }
53+
>x : undefined
54+
>x = undefined : undefined
55+
>x : number
56+
>undefined : undefined
57+
>a : { x?: number | undefined; y?: number | undefined; }
58+
59+
({ y: x = undefined } = a);
60+
>({ y: x = undefined } = a) : { x?: number | undefined; y?: number | undefined; }
61+
>{ y: x = undefined } = a : { x?: number | undefined; y?: number | undefined; }
62+
>{ y: x = undefined } : { y?: undefined; }
63+
>y : undefined
64+
>x = undefined : undefined
65+
>x : number
66+
>undefined : undefined
67+
>a : { x?: number | undefined; y?: number | undefined; }
68+
69+
const { x: z1 } = a;
70+
>x : any
71+
>z1 : number | undefined
72+
>a : { x?: number | undefined; y?: number | undefined; }
73+
74+
const { x: z2 = 0 } = a;
75+
>x : any
76+
>z2 : number
77+
>0 : 0
78+
>a : { x?: number | undefined; y?: number | undefined; }
79+
80+
const { x: z3 = undefined } = a;
81+
>x : any
82+
>z3 : number | undefined
83+
>undefined : undefined
84+
>a : { x?: number | undefined; y?: number | undefined; }
85+
86+
87+
declare const r: Iterator<number>;
88+
>r : Iterator<number, any, undefined>
89+
90+
let done: boolean;
91+
>done : boolean
92+
93+
let value;
94+
>value : any
95+
96+
({ done = false, value } = r.next());
97+
>({ done = false, value } = r.next()) : IteratorResult<number, any>
98+
>{ done = false, value } = r.next() : IteratorResult<number, any>
99+
>{ done = false, value } : { done?: boolean; value: any; }
100+
>done : boolean
101+
>false : false
102+
>value : any
103+
>r.next() : IteratorResult<number, any>
104+
>r.next : (...args: [] | [undefined]) => IteratorResult<number, any>
105+
>r : Iterator<number, any, undefined>
106+
>next : (...args: [] | [undefined]) => IteratorResult<number, any>
107+
108+
({ done: done = false, value } = r.next());
109+
>({ done: done = false, value } = r.next()) : IteratorResult<number, any>
110+
>{ done: done = false, value } = r.next() : IteratorResult<number, any>
111+
>{ done: done = false, value } : { done?: boolean; value: any; }
112+
>done : boolean
113+
>done = false : false
114+
>done : boolean
115+
>false : false
116+
>value : any
117+
>r.next() : IteratorResult<number, any>
118+
>r.next : (...args: [] | [undefined]) => IteratorResult<number, any>
119+
>r : Iterator<number, any, undefined>
120+
>next : (...args: [] | [undefined]) => IteratorResult<number, any>
121+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// @lib: es2015
2+
// @strictNullChecks: true
3+
const a: { x?: number; y?: number } = { };
4+
5+
let x: number;
6+
7+
// Should not error out
8+
({ x = 0 } = a);
9+
({ x: x = 0} = a);
10+
({ y: x = 0} = a);
11+
12+
// Should be error
13+
({ x = undefined } = a);
14+
({ x: x = undefined } = a);
15+
({ y: x = undefined } = a);
16+
17+
const { x: z1 } = a;
18+
const { x: z2 = 0 } = a;
19+
const { x: z3 = undefined } = a;
20+
21+
22+
declare const r: Iterator<number>;
23+
let done: boolean;
24+
let value;
25+
26+
({ done = false, value } = r.next());
27+
({ done: done = false, value } = r.next());

0 commit comments

Comments
 (0)