Skip to content

Commit ee46bde

Browse files
committed
Make any[] the effective rest type when any is spread
1 parent 747e741 commit ee46bde

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20837,8 +20837,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2083720837
const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
2083820838

2083920839
for (let i = 0; i < paramCount; i++) {
20840-
const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i);
20841-
const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i);
20840+
const sourceType = i === restIndex ? getRestOrAnyTypeAtPosition(source, i) : tryGetTypeAtPosition(source, i);
20841+
const targetType = i === restIndex ? getRestOrAnyTypeAtPosition(target, i) : tryGetTypeAtPosition(target, i);
2084220842
if (sourceType && targetType) {
2084320843
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
2084420844
// how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
@@ -36464,6 +36464,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3646436464
return createTupleType(types, flags, readonly, names);
3646536465
}
3646636466

36467+
// Return the rest type at the given position, transforming `any[]` into just `any`. We do this because
36468+
// in signatures we want `any[]` in a rest position to be compatible with anything, but `any[]` isn't
36469+
// assignable to tuple types with required elements.
36470+
function getRestOrAnyTypeAtPosition(source: Signature, pos: number): Type {
36471+
const restType = getRestTypeAtPosition(source, pos);
36472+
const elementType = restType && getElementTypeOfArrayType(restType);
36473+
return elementType && isTypeAny(elementType) ? anyType : restType;
36474+
}
36475+
3646736476
// Return the number of parameters in a signature. The rest parameter, if present, counts as one
3646836477
// parameter. For example, the parameter count of (x: number, y: number, ...z: string[]) is 3 and
3646936478
// the parameter count of (x: number, ...args: [number, ...string[], boolean])) is also 3. In the
@@ -36527,7 +36536,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3652736536
if (signatureHasRestParameter(signature)) {
3652836537
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
3652936538
if (!isTupleType(restType)) {
36530-
return restType;
36539+
return isTypeAny(restType) ? anyArrayType : restType;
3653136540
}
3653236541
if (restType.target.hasRestElement) {
3653336542
return sliceTupleType(restType, restType.target.fixedLength);

0 commit comments

Comments
 (0)