Skip to content

Commit 7c9dc34

Browse files
committed
Relate non-augmenting array subtypes without resorting to structural comparison
1 parent b0c2860 commit 7c9dc34

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

src/compiler/checker.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18219,6 +18219,22 @@ namespace ts {
1821918219
return result;
1822018220
}
1822118221

18222+
if (isNonAugmentingArraySubtype(source) && isArrayType(target)) {
18223+
let sourceBase = getBaseTypes((source as TypeReference).target as InterfaceType)[0];
18224+
if (length((target as TypeReference).resolvedTypeArguments) === 2) {
18225+
sourceBase = getTypeWithThisArgument(sourceBase, ((source as TypeReference).target as InterfaceType).thisType);
18226+
}
18227+
return isRelatedTo(sourceBase, target, reportErrors);
18228+
}
18229+
18230+
if (isArrayType(source) && isNonAugmentingArraySubtype(target)) {
18231+
let targetBase = getBaseTypes((target as TypeReference).target as InterfaceType)[0];
18232+
if (length((source as TypeReference).resolvedTypeArguments) === 2) {
18233+
targetBase = getTypeWithThisArgument(targetBase, ((target as TypeReference).target as InterfaceType).thisType);
18234+
}
18235+
return isRelatedTo(source, targetBase, reportErrors);
18236+
}
18237+
1822218238
if (target.flags & TypeFlags.TypeParameter) {
1822318239
// A source type { [P in Q]: X } is related to a target type T if keyof T is related to Q and X is related to T[Q].
1822418240
if (getObjectFlags(source) & ObjectFlags.Mapped && !(<MappedType>source).declaration.nameType && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(<MappedType>source))) {
@@ -19868,6 +19884,24 @@ namespace ts {
1986819884
return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
1986919885
}
1987019886

19887+
function isNonAugmentingArraySubtype(type: Type) {
19888+
if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) {
19889+
return false;
19890+
}
19891+
const target = (type as TypeReference).target as InterfaceType;
19892+
const bases = getBaseTypes(target);
19893+
if (bases.length !== 1) {
19894+
return false;
19895+
}
19896+
if (!isArrayType(bases[0])) {
19897+
return false;
19898+
}
19899+
if (getMembersOfSymbol(type.symbol).size) {
19900+
return false; // If the interface has any members, they may subtype members in the base, so we should do a full structural comparison
19901+
}
19902+
return true;
19903+
}
19904+
1987119905
function isEmptyArrayLiteralType(type: Type): boolean {
1987219906
const elementType = getElementTypeOfArrayType(type);
1987319907
return strictNullChecks ? elementType === implicitNeverType : elementType === undefinedWideningType;

tests/baselines/reference/arrayLiterals3.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(17,5): error
88
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(33,5): error TS2322: Type 'number[]' is not assignable to type '[number, number, number]'.
99
Target requires 3 element(s) but source may have fewer.
1010
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error TS2322: Type '(string | number)[]' is not assignable to type 'myArray'.
11-
The types returned by 'pop()' are incompatible between these types.
11+
Type '(string | number)[]' is not assignable to type 'Number[]'.
1212
Type 'string | number' is not assignable to type 'Number'.
1313
Type 'string' is not assignable to type 'Number'.
1414

@@ -65,7 +65,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
6565
var c2: myArray = [...temp1, ...temp]; // Error cannot assign (number|string)[] to number[]
6666
~~
6767
!!! error TS2322: Type '(string | number)[]' is not assignable to type 'myArray'.
68-
!!! error TS2322: The types returned by 'pop()' are incompatible between these types.
68+
!!! error TS2322: Type '(string | number)[]' is not assignable to type 'Number[]'.
6969
!!! error TS2322: Type 'string | number' is not assignable to type 'Number'.
7070
!!! error TS2322: Type 'string' is not assignable to type 'Number'.
7171

0 commit comments

Comments
 (0)