Ensure empty array literal is assignable to never[] (#47816)

* Ensure empty array literal is assignable to never[]

* Add tests

* Add comment
This commit is contained in:
Anders Hejlsberg
2022-02-12 16:39:21 +01:00
committed by GitHub
parent 2bdbc8fe7b
commit 78ef3e70c9
11 changed files with 311 additions and 2 deletions

View File

@@ -17907,8 +17907,10 @@ namespace ts {
(source as LiteralType).value === (target as LiteralType).value &&
isEnumTypeRelatedTo(getParentOfSymbol(source.symbol)!, getParentOfSymbol(target.symbol)!, errorReporter)) return true;
}
if (s & TypeFlags.Undefined && (!strictNullChecks || t & (TypeFlags.Undefined | TypeFlags.Void))) return true;
if (s & TypeFlags.Null && (!strictNullChecks || t & TypeFlags.Null)) return true;
// In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`.
// Since unions and intersections may reduce to `never`, we exclude them here.
if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true;
if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true;
if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive) return true;
if (relation === assignableRelation || relation === comparableRelation) {
if (s & TypeFlags.Any) return true;
@@ -19427,6 +19429,11 @@ namespace ts {
}
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target &&
!isTupleType(source) && !(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) {
// When strictNullChecks is disabled, the element type of the empty array literal is undefinedWideningType,
// and an empty array literal wouldn't be assignable to a `never[]` without this check.
if (isEmptyArrayLiteralType(source)) {
return Ternary.True;
}
// We have type references to the same generic type, and the type references are not marker
// type references (which are intended by be compared structurally). Obtain the variance
// information for the type parameters and relate the type arguments accordingly.

View File

@@ -63,4 +63,26 @@ tests/cases/conformance/types/never/neverTypeErrors1.ts(24,17): error TS2407: Th
for (const n in f4()) {}
~~~~
!!! 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'.
function f5() {
let x: never[] = []; // Ok
}
// Repro from #46032
interface A {
foo: "a";
}
interface B {
foo: "b";
}
type Union = A & B;
function func(): { value: Union[] } {
return {
value: [],
};
}

View File

@@ -23,6 +23,28 @@ function f4(): never {
for (const n of f4()) {}
for (const n in f4()) {}
function f5() {
let x: never[] = []; // Ok
}
// Repro from #46032
interface A {
foo: "a";
}
interface B {
foo: "b";
}
type Union = A & B;
function func(): { value: Union[] } {
return {
value: [],
};
}
//// [neverTypeErrors1.js]
@@ -48,3 +70,11 @@ for (var _i = 0, _a = f4(); _i < _a.length; _i++) {
var n = _a[_i];
}
for (var n in f4()) { }
function f5() {
var x = []; // Ok
}
function func() {
return {
value: []
};
}

View File

@@ -52,3 +52,43 @@ for (const n in f4()) {}
>n : Symbol(n, Decl(neverTypeErrors1.ts, 23, 10))
>f4 : Symbol(f4, Decl(neverTypeErrors1.ts, 17, 1))
function f5() {
>f5 : Symbol(f5, Decl(neverTypeErrors1.ts, 23, 24))
let x: never[] = []; // Ok
>x : Symbol(x, Decl(neverTypeErrors1.ts, 26, 7))
}
// Repro from #46032
interface A {
>A : Symbol(A, Decl(neverTypeErrors1.ts, 27, 1))
foo: "a";
>foo : Symbol(A.foo, Decl(neverTypeErrors1.ts, 31, 13))
}
interface B {
>B : Symbol(B, Decl(neverTypeErrors1.ts, 33, 1))
foo: "b";
>foo : Symbol(B.foo, Decl(neverTypeErrors1.ts, 35, 13))
}
type Union = A & B;
>Union : Symbol(Union, Decl(neverTypeErrors1.ts, 37, 1))
>A : Symbol(A, Decl(neverTypeErrors1.ts, 27, 1))
>B : Symbol(B, Decl(neverTypeErrors1.ts, 33, 1))
function func(): { value: Union[] } {
>func : Symbol(func, Decl(neverTypeErrors1.ts, 39, 19))
>value : Symbol(value, Decl(neverTypeErrors1.ts, 41, 18))
>Union : Symbol(Union, Decl(neverTypeErrors1.ts, 37, 1))
return {
value: [],
>value : Symbol(value, Decl(neverTypeErrors1.ts, 42, 12))
};
}

View File

@@ -67,3 +67,40 @@ for (const n in f4()) {}
>f4() : never
>f4 : () => never
function f5() {
>f5 : () => void
let x: never[] = []; // Ok
>x : never[]
>[] : undefined[]
}
// Repro from #46032
interface A {
foo: "a";
>foo : "a"
}
interface B {
foo: "b";
>foo : "b"
}
type Union = A & B;
>Union : never
function func(): { value: Union[] } {
>func : () => { value: Union[];}
>value : never[]
return {
>{ value: [], } : { value: undefined[]; }
value: [],
>value : undefined[]
>[] : undefined[]
};
}

View File

@@ -63,4 +63,26 @@ tests/cases/conformance/types/never/neverTypeErrors2.ts(24,17): error TS2407: Th
for (const n in f4()) {}
~~~~
!!! 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'.
function f5() {
let x: never[] = []; // Ok
}
// Repro from #46032
interface A {
foo: "a";
}
interface B {
foo: "b";
}
type Union = A & B;
function func(): { value: Union[] } {
return {
value: [],
};
}

View File

@@ -23,6 +23,28 @@ function f4(): never {
for (const n of f4()) {}
for (const n in f4()) {}
function f5() {
let x: never[] = []; // Ok
}
// Repro from #46032
interface A {
foo: "a";
}
interface B {
foo: "b";
}
type Union = A & B;
function func(): { value: Union[] } {
return {
value: [],
};
}
//// [neverTypeErrors2.js]
@@ -48,3 +70,11 @@ for (var _i = 0, _a = f4(); _i < _a.length; _i++) {
var n = _a[_i];
}
for (var n in f4()) { }
function f5() {
var x = []; // Ok
}
function func() {
return {
value: []
};
}

View File

@@ -52,3 +52,43 @@ for (const n in f4()) {}
>n : Symbol(n, Decl(neverTypeErrors2.ts, 23, 10))
>f4 : Symbol(f4, Decl(neverTypeErrors2.ts, 17, 1))
function f5() {
>f5 : Symbol(f5, Decl(neverTypeErrors2.ts, 23, 24))
let x: never[] = []; // Ok
>x : Symbol(x, Decl(neverTypeErrors2.ts, 26, 7))
}
// Repro from #46032
interface A {
>A : Symbol(A, Decl(neverTypeErrors2.ts, 27, 1))
foo: "a";
>foo : Symbol(A.foo, Decl(neverTypeErrors2.ts, 31, 13))
}
interface B {
>B : Symbol(B, Decl(neverTypeErrors2.ts, 33, 1))
foo: "b";
>foo : Symbol(B.foo, Decl(neverTypeErrors2.ts, 35, 13))
}
type Union = A & B;
>Union : Symbol(Union, Decl(neverTypeErrors2.ts, 37, 1))
>A : Symbol(A, Decl(neverTypeErrors2.ts, 27, 1))
>B : Symbol(B, Decl(neverTypeErrors2.ts, 33, 1))
function func(): { value: Union[] } {
>func : Symbol(func, Decl(neverTypeErrors2.ts, 39, 19))
>value : Symbol(value, Decl(neverTypeErrors2.ts, 41, 18))
>Union : Symbol(Union, Decl(neverTypeErrors2.ts, 37, 1))
return {
value: [],
>value : Symbol(value, Decl(neverTypeErrors2.ts, 42, 12))
};
}

View File

@@ -67,3 +67,40 @@ for (const n in f4()) {}
>f4() : never
>f4 : () => never
function f5() {
>f5 : () => void
let x: never[] = []; // Ok
>x : never[]
>[] : never[]
}
// Repro from #46032
interface A {
foo: "a";
>foo : "a"
}
interface B {
foo: "b";
>foo : "b"
}
type Union = A & B;
>Union : never
function func(): { value: Union[] } {
>func : () => { value: Union[];}
>value : never[]
return {
>{ value: [], } : { value: never[]; }
value: [],
>value : never[]
>[] : never[]
};
}

View File

@@ -22,3 +22,25 @@ function f4(): never {
for (const n of f4()) {}
for (const n in f4()) {}
function f5() {
let x: never[] = []; // Ok
}
// Repro from #46032
interface A {
foo: "a";
}
interface B {
foo: "b";
}
type Union = A & B;
function func(): { value: Union[] } {
return {
value: [],
};
}

View File

@@ -24,3 +24,25 @@ function f4(): never {
for (const n of f4()) {}
for (const n in f4()) {}
function f5() {
let x: never[] = []; // Ok
}
// Repro from #46032
interface A {
foo: "a";
}
interface B {
foo: "b";
}
type Union = A & B;
function func(): { value: Union[] } {
return {
value: [],
};
}