Skip to content

Commit 78ef3e7

Browse files
authored
Ensure empty array literal is assignable to never[] (microsoft#47816)
* Ensure empty array literal is assignable to never[] * Add tests * Add comment
1 parent 2bdbc8f commit 78ef3e7

File tree

11 files changed

+311
-2
lines changed

11 files changed

+311
-2
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17907,8 +17907,10 @@ namespace ts {
1790717907
(source as LiteralType).value === (target as LiteralType).value &&
1790817908
isEnumTypeRelatedTo(getParentOfSymbol(source.symbol)!, getParentOfSymbol(target.symbol)!, errorReporter)) return true;
1790917909
}
17910-
if (s & TypeFlags.Undefined && (!strictNullChecks || t & (TypeFlags.Undefined | TypeFlags.Void))) return true;
17911-
if (s & TypeFlags.Null && (!strictNullChecks || t & TypeFlags.Null)) return true;
17910+
// In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`.
17911+
// Since unions and intersections may reduce to `never`, we exclude them here.
17912+
if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true;
17913+
if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true;
1791217914
if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive) return true;
1791317915
if (relation === assignableRelation || relation === comparableRelation) {
1791417916
if (s & TypeFlags.Any) return true;
@@ -19427,6 +19429,11 @@ namespace ts {
1942719429
}
1942819430
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target &&
1942919431
!isTupleType(source) && !(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) {
19432+
// When strictNullChecks is disabled, the element type of the empty array literal is undefinedWideningType,
19433+
// and an empty array literal wouldn't be assignable to a `never[]` without this check.
19434+
if (isEmptyArrayLiteralType(source)) {
19435+
return Ternary.True;
19436+
}
1943019437
// We have type references to the same generic type, and the type references are not marker
1943119438
// type references (which are intended by be compared structurally). Obtain the variance
1943219439
// information for the type parameters and relate the type arguments accordingly.

tests/baselines/reference/neverTypeErrors1.errors.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,26 @@ tests/cases/conformance/types/never/neverTypeErrors1.ts(24,17): error TS2407: Th
6363
for (const n in f4()) {}
6464
~~~~
6565
!!! error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.
66+
67+
function f5() {
68+
let x: never[] = []; // Ok
69+
}
70+
71+
// Repro from #46032
72+
73+
interface A {
74+
foo: "a";
75+
}
76+
77+
interface B {
78+
foo: "b";
79+
}
80+
81+
type Union = A & B;
82+
83+
function func(): { value: Union[] } {
84+
return {
85+
value: [],
86+
};
87+
}
6688

tests/baselines/reference/neverTypeErrors1.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,28 @@ function f4(): never {
2323

2424
for (const n of f4()) {}
2525
for (const n in f4()) {}
26+
27+
function f5() {
28+
let x: never[] = []; // Ok
29+
}
30+
31+
// Repro from #46032
32+
33+
interface A {
34+
foo: "a";
35+
}
36+
37+
interface B {
38+
foo: "b";
39+
}
40+
41+
type Union = A & B;
42+
43+
function func(): { value: Union[] } {
44+
return {
45+
value: [],
46+
};
47+
}
2648

2749

2850
//// [neverTypeErrors1.js]
@@ -48,3 +70,11 @@ for (var _i = 0, _a = f4(); _i < _a.length; _i++) {
4870
var n = _a[_i];
4971
}
5072
for (var n in f4()) { }
73+
function f5() {
74+
var x = []; // Ok
75+
}
76+
function func() {
77+
return {
78+
value: []
79+
};
80+
}

tests/baselines/reference/neverTypeErrors1.symbols

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,43 @@ for (const n in f4()) {}
5252
>n : Symbol(n, Decl(neverTypeErrors1.ts, 23, 10))
5353
>f4 : Symbol(f4, Decl(neverTypeErrors1.ts, 17, 1))
5454

55+
function f5() {
56+
>f5 : Symbol(f5, Decl(neverTypeErrors1.ts, 23, 24))
57+
58+
let x: never[] = []; // Ok
59+
>x : Symbol(x, Decl(neverTypeErrors1.ts, 26, 7))
60+
}
61+
62+
// Repro from #46032
63+
64+
interface A {
65+
>A : Symbol(A, Decl(neverTypeErrors1.ts, 27, 1))
66+
67+
foo: "a";
68+
>foo : Symbol(A.foo, Decl(neverTypeErrors1.ts, 31, 13))
69+
}
70+
71+
interface B {
72+
>B : Symbol(B, Decl(neverTypeErrors1.ts, 33, 1))
73+
74+
foo: "b";
75+
>foo : Symbol(B.foo, Decl(neverTypeErrors1.ts, 35, 13))
76+
}
77+
78+
type Union = A & B;
79+
>Union : Symbol(Union, Decl(neverTypeErrors1.ts, 37, 1))
80+
>A : Symbol(A, Decl(neverTypeErrors1.ts, 27, 1))
81+
>B : Symbol(B, Decl(neverTypeErrors1.ts, 33, 1))
82+
83+
function func(): { value: Union[] } {
84+
>func : Symbol(func, Decl(neverTypeErrors1.ts, 39, 19))
85+
>value : Symbol(value, Decl(neverTypeErrors1.ts, 41, 18))
86+
>Union : Symbol(Union, Decl(neverTypeErrors1.ts, 37, 1))
87+
88+
return {
89+
value: [],
90+
>value : Symbol(value, Decl(neverTypeErrors1.ts, 42, 12))
91+
92+
};
93+
}
94+

tests/baselines/reference/neverTypeErrors1.types

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,40 @@ for (const n in f4()) {}
6767
>f4() : never
6868
>f4 : () => never
6969

70+
function f5() {
71+
>f5 : () => void
72+
73+
let x: never[] = []; // Ok
74+
>x : never[]
75+
>[] : undefined[]
76+
}
77+
78+
// Repro from #46032
79+
80+
interface A {
81+
foo: "a";
82+
>foo : "a"
83+
}
84+
85+
interface B {
86+
foo: "b";
87+
>foo : "b"
88+
}
89+
90+
type Union = A & B;
91+
>Union : never
92+
93+
function func(): { value: Union[] } {
94+
>func : () => { value: Union[];}
95+
>value : never[]
96+
97+
return {
98+
>{ value: [], } : { value: undefined[]; }
99+
100+
value: [],
101+
>value : undefined[]
102+
>[] : undefined[]
103+
104+
};
105+
}
106+

tests/baselines/reference/neverTypeErrors2.errors.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,26 @@ tests/cases/conformance/types/never/neverTypeErrors2.ts(24,17): error TS2407: Th
6363
for (const n in f4()) {}
6464
~~~~
6565
!!! error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.
66+
67+
function f5() {
68+
let x: never[] = []; // Ok
69+
}
70+
71+
// Repro from #46032
72+
73+
interface A {
74+
foo: "a";
75+
}
76+
77+
interface B {
78+
foo: "b";
79+
}
80+
81+
type Union = A & B;
82+
83+
function func(): { value: Union[] } {
84+
return {
85+
value: [],
86+
};
87+
}
6688

tests/baselines/reference/neverTypeErrors2.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,28 @@ function f4(): never {
2323

2424
for (const n of f4()) {}
2525
for (const n in f4()) {}
26+
27+
function f5() {
28+
let x: never[] = []; // Ok
29+
}
30+
31+
// Repro from #46032
32+
33+
interface A {
34+
foo: "a";
35+
}
36+
37+
interface B {
38+
foo: "b";
39+
}
40+
41+
type Union = A & B;
42+
43+
function func(): { value: Union[] } {
44+
return {
45+
value: [],
46+
};
47+
}
2648

2749

2850
//// [neverTypeErrors2.js]
@@ -48,3 +70,11 @@ for (var _i = 0, _a = f4(); _i < _a.length; _i++) {
4870
var n = _a[_i];
4971
}
5072
for (var n in f4()) { }
73+
function f5() {
74+
var x = []; // Ok
75+
}
76+
function func() {
77+
return {
78+
value: []
79+
};
80+
}

tests/baselines/reference/neverTypeErrors2.symbols

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,43 @@ for (const n in f4()) {}
5252
>n : Symbol(n, Decl(neverTypeErrors2.ts, 23, 10))
5353
>f4 : Symbol(f4, Decl(neverTypeErrors2.ts, 17, 1))
5454

55+
function f5() {
56+
>f5 : Symbol(f5, Decl(neverTypeErrors2.ts, 23, 24))
57+
58+
let x: never[] = []; // Ok
59+
>x : Symbol(x, Decl(neverTypeErrors2.ts, 26, 7))
60+
}
61+
62+
// Repro from #46032
63+
64+
interface A {
65+
>A : Symbol(A, Decl(neverTypeErrors2.ts, 27, 1))
66+
67+
foo: "a";
68+
>foo : Symbol(A.foo, Decl(neverTypeErrors2.ts, 31, 13))
69+
}
70+
71+
interface B {
72+
>B : Symbol(B, Decl(neverTypeErrors2.ts, 33, 1))
73+
74+
foo: "b";
75+
>foo : Symbol(B.foo, Decl(neverTypeErrors2.ts, 35, 13))
76+
}
77+
78+
type Union = A & B;
79+
>Union : Symbol(Union, Decl(neverTypeErrors2.ts, 37, 1))
80+
>A : Symbol(A, Decl(neverTypeErrors2.ts, 27, 1))
81+
>B : Symbol(B, Decl(neverTypeErrors2.ts, 33, 1))
82+
83+
function func(): { value: Union[] } {
84+
>func : Symbol(func, Decl(neverTypeErrors2.ts, 39, 19))
85+
>value : Symbol(value, Decl(neverTypeErrors2.ts, 41, 18))
86+
>Union : Symbol(Union, Decl(neverTypeErrors2.ts, 37, 1))
87+
88+
return {
89+
value: [],
90+
>value : Symbol(value, Decl(neverTypeErrors2.ts, 42, 12))
91+
92+
};
93+
}
94+

tests/baselines/reference/neverTypeErrors2.types

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,40 @@ for (const n in f4()) {}
6767
>f4() : never
6868
>f4 : () => never
6969

70+
function f5() {
71+
>f5 : () => void
72+
73+
let x: never[] = []; // Ok
74+
>x : never[]
75+
>[] : never[]
76+
}
77+
78+
// Repro from #46032
79+
80+
interface A {
81+
foo: "a";
82+
>foo : "a"
83+
}
84+
85+
interface B {
86+
foo: "b";
87+
>foo : "b"
88+
}
89+
90+
type Union = A & B;
91+
>Union : never
92+
93+
function func(): { value: Union[] } {
94+
>func : () => { value: Union[];}
95+
>value : never[]
96+
97+
return {
98+
>{ value: [], } : { value: never[]; }
99+
100+
value: [],
101+
>value : never[]
102+
>[] : never[]
103+
104+
};
105+
}
106+

tests/cases/conformance/types/never/neverTypeErrors1.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,25 @@ function f4(): never {
2222

2323
for (const n of f4()) {}
2424
for (const n in f4()) {}
25+
26+
function f5() {
27+
let x: never[] = []; // Ok
28+
}
29+
30+
// Repro from #46032
31+
32+
interface A {
33+
foo: "a";
34+
}
35+
36+
interface B {
37+
foo: "b";
38+
}
39+
40+
type Union = A & B;
41+
42+
function func(): { value: Union[] } {
43+
return {
44+
value: [],
45+
};
46+
}

tests/cases/conformance/types/never/neverTypeErrors2.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,25 @@ function f4(): never {
2424

2525
for (const n of f4()) {}
2626
for (const n in f4()) {}
27+
28+
function f5() {
29+
let x: never[] = []; // Ok
30+
}
31+
32+
// Repro from #46032
33+
34+
interface A {
35+
foo: "a";
36+
}
37+
38+
interface B {
39+
foo: "b";
40+
}
41+
42+
type Union = A & B;
43+
44+
function func(): { value: Union[] } {
45+
return {
46+
value: [],
47+
};
48+
}

0 commit comments

Comments
 (0)