Skip to content
Merged
43 changes: 36 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24307,13 +24307,42 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
else {
const middleLength = targetArity - startLength - endLength;
if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
// Middle of target is [...T, ...U] and source is tuple type
const targetInfo = getInferenceInfoForType(elementTypes[startLength]);
if (targetInfo && targetInfo.impliedArity !== undefined) {
// Infer slices from source based on implied arity of T.
inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]);
inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]);
if (middleLength === 2) {
if (elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
// Middle of target is [...T, ...U] and source is tuple type
const targetInfo = getInferenceInfoForType(elementTypes[startLength]);
if (targetInfo && targetInfo.impliedArity !== undefined) {
// Infer slices from source based on implied arity of T.
inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]);
inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]);
}
}
else if (elementFlags[startLength] & ElementFlags.Variadic && elementFlags[startLength + 1] & ElementFlags.Rest) {
// Middle of target is [...T, ...rest] and source is tuple type
// if T is constrained by a fixed-size tuple we might be able to use its arity to infer T
const param = getInferenceInfoForType(elementTypes[startLength])?.typeParameter;
const constraint = param && getBaseConstraintOfType(param);
if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) {
const impliedArity = constraint.target.fixedLength;
inferFromTypes(sliceTupleType(source, startLength, sourceArity - (startLength + impliedArity)), elementTypes[startLength]);
inferFromTypes(getElementTypeOfSliceOfTupleType(source, startLength + impliedArity, endLength)!, elementTypes[startLength + 1]);
}
}
else if (elementFlags[startLength] & ElementFlags.Rest && elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
// Middle of target is [...rest, ...T] and source is tuple type
// if T is constrained by a fixed-size tuple we might be able to use its arity to infer T
const param = getInferenceInfoForType(elementTypes[startLength + 1])?.typeParameter;
const constraint = param && getBaseConstraintOfType(param);
if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) {
const impliedArity = constraint.target.fixedLength;
const endIndex = sourceArity - getEndElementCount(target.target, ElementFlags.Fixed);
const startIndex = endIndex - impliedArity;
const trailingSlice = createTupleType(getTypeArguments(source).slice(startIndex, endIndex), source.target.elementFlags.slice(startIndex, endIndex),
/*readonly*/ false, source.target.labeledElementDeclarations && source.target.labeledElementDeclarations.slice(startIndex, endIndex));

inferFromTypes(getElementTypeOfSliceOfTupleType(source, startLength, endLength + impliedArity)!, elementTypes[startLength]);
inferFromTypes(trailingSlice, elementTypes[startLength + 1]);
}
}
}
else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
=== tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts ===
// repro #51138

type SubTup2FixedLength<T extends unknown[]> = T extends [
>SubTup2FixedLength : Symbol(SubTup2FixedLength, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 0, 0))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 2, 24))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 2, 24))

...infer B extends [any, any],
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 3, 10))

any
]
? B
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 3, 10))

: never;

type SubTup2FixedLengthTest = SubTup2FixedLength<[a: 0, b: 1, c: 2]>;
>SubTup2FixedLengthTest : Symbol(SubTup2FixedLengthTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 7, 10))
>SubTup2FixedLength : Symbol(SubTup2FixedLength, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 0, 0))

type SubTup2Variadic<T extends unknown[]> = T extends [
>SubTup2Variadic : Symbol(SubTup2Variadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 9, 69))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 11, 21))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 11, 21))

...infer B extends [any, any],
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 12, 10))

...any
]
? B
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 12, 10))

: never;

type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: 2[]]>;
>SubTup2VariadicTest : Symbol(SubTup2VariadicTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 16, 10))
>SubTup2Variadic : Symbol(SubTup2Variadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 9, 69))

type SubTup2VariadicTest2 = SubTup2Variadic<[a: 0, b: 1, c: 2, ...d: 3[]]>;
>SubTup2VariadicTest2 : Symbol(SubTup2VariadicTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 18, 68))
>SubTup2Variadic : Symbol(SubTup2Variadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 9, 69))

type SubTup2VariadicAndRest<T extends unknown[]> = T extends [
>SubTup2VariadicAndRest : Symbol(SubTup2VariadicAndRest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 19, 75))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 21, 28))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 21, 28))

...infer B extends [any, any],
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 22, 12))

...(infer C)[]
>C : Symbol(C, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 23, 13))

]
? [...B, ...[C]]
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 22, 12))
>C : Symbol(C, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 23, 13))

: never;

type SubTup2VariadicAndRestTest = SubTup2VariadicAndRest<[a: 0, b: 1, ...c: 2[]]>;
>SubTup2VariadicAndRestTest : Symbol(SubTup2VariadicAndRestTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 26, 12))
>SubTup2VariadicAndRest : Symbol(SubTup2VariadicAndRest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 19, 75))

type SubTup2TrailingVariadic<T extends unknown[]> = T extends [
>SubTup2TrailingVariadic : Symbol(SubTup2TrailingVariadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 28, 82))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 30, 29))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 30, 29))

...any,
...infer B extends [any, any],
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 32, 10))

]
? B
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 32, 10))

: never;

type SubTup2TrailingVariadicTest = SubTup2TrailingVariadic<[...a: 0[], b: 1, c: 2]>;
>SubTup2TrailingVariadicTest : Symbol(SubTup2TrailingVariadicTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 35, 10))
>SubTup2TrailingVariadic : Symbol(SubTup2TrailingVariadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 28, 82))

type SubTup2TrailingVariadicTest2 = SubTup2TrailingVariadic<[...a: 0[], b: 1, c: 2, d: 3]>;
>SubTup2TrailingVariadicTest2 : Symbol(SubTup2TrailingVariadicTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 37, 84))
>SubTup2TrailingVariadic : Symbol(SubTup2TrailingVariadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 28, 82))

type SubTup2RestAndTrailingVariadic2<T extends unknown[]> = T extends [
>SubTup2RestAndTrailingVariadic2 : Symbol(SubTup2RestAndTrailingVariadic2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 38, 91))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 40, 37))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 40, 37))

...(infer C)[],
>C : Symbol(C, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 41, 13))

...infer B extends [any, any],
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 42, 12))

]
? [C, ...B]
>C : Symbol(C, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 41, 13))
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 42, 12))

: never;

type SubTup2RestAndTrailingVariadic2Test = SubTup2RestAndTrailingVariadic2<[...a: 0[], b: 1, c: 2]>;
>SubTup2RestAndTrailingVariadic2Test : Symbol(SubTup2RestAndTrailingVariadic2Test, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 45, 12))
>SubTup2RestAndTrailingVariadic2 : Symbol(SubTup2RestAndTrailingVariadic2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 38, 91))

type SubTup2VariadicWithLeadingFixedElements<T extends unknown[]> = T extends [
>SubTup2VariadicWithLeadingFixedElements : Symbol(SubTup2VariadicWithLeadingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 47, 100))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 49, 45))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 49, 45))

any,
...infer B extends [any, any],
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 51, 10))

...any
]
? B
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 51, 10))

: never;

type SubTup2VariadicWithLeadingFixedElementsTest = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, ...d: 3[]]>;
>SubTup2VariadicWithLeadingFixedElementsTest : Symbol(SubTup2VariadicWithLeadingFixedElementsTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 55, 10))
>SubTup2VariadicWithLeadingFixedElements : Symbol(SubTup2VariadicWithLeadingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 47, 100))

type SubTup2VariadicWithLeadingFixedElementsTest2 = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, d: 3, ...e: 4[]]>;
>SubTup2VariadicWithLeadingFixedElementsTest2 : Symbol(SubTup2VariadicWithLeadingFixedElementsTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 57, 122))
>SubTup2VariadicWithLeadingFixedElements : Symbol(SubTup2VariadicWithLeadingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 47, 100))

type SubTup2TrailingVariadicWithTrailingFixedElements<T extends unknown[]> = T extends [
>SubTup2TrailingVariadicWithTrailingFixedElements : Symbol(SubTup2TrailingVariadicWithTrailingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 58, 129))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 60, 54))
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 60, 54))

...any,
...infer B extends [any, any],
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 62, 10))

any,
]
? B
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 62, 10))

: never;

type SubTup2TrailingVariadicWithTrailingFixedElementsTest = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: 0[], b: 1, c: 2, d: 3]>;
>SubTup2TrailingVariadicWithTrailingFixedElementsTest : Symbol(SubTup2TrailingVariadicWithTrailingFixedElementsTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 66, 10))
>SubTup2TrailingVariadicWithTrailingFixedElements : Symbol(SubTup2TrailingVariadicWithTrailingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 58, 129))

type SubTup2TrailingVariadicWithTrailingFixedElementsTest2 = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: 0[], b: 1, c: 2, d: 3, e: 4]>;
>SubTup2TrailingVariadicWithTrailingFixedElementsTest2 : Symbol(SubTup2TrailingVariadicWithTrailingFixedElementsTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 68, 140))
>SubTup2TrailingVariadicWithTrailingFixedElements : Symbol(SubTup2TrailingVariadicWithTrailingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 58, 129))

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
=== tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts ===
// repro #51138

type SubTup2FixedLength<T extends unknown[]> = T extends [
>SubTup2FixedLength : SubTup2FixedLength<T>

...infer B extends [any, any],
any
]
? B
: never;

type SubTup2FixedLengthTest = SubTup2FixedLength<[a: 0, b: 1, c: 2]>;
>SubTup2FixedLengthTest : [a: 0, b: 1]

type SubTup2Variadic<T extends unknown[]> = T extends [
>SubTup2Variadic : SubTup2Variadic<T>

...infer B extends [any, any],
...any
]
? B
: never;

type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: 2[]]>;
>SubTup2VariadicTest : [a: 0, b: 1]

type SubTup2VariadicTest2 = SubTup2Variadic<[a: 0, b: 1, c: 2, ...d: 3[]]>;
>SubTup2VariadicTest2 : [a: 0, b: 1]

type SubTup2VariadicAndRest<T extends unknown[]> = T extends [
>SubTup2VariadicAndRest : SubTup2VariadicAndRest<T>

...infer B extends [any, any],
...(infer C)[]
]
? [...B, ...[C]]
: never;

type SubTup2VariadicAndRestTest = SubTup2VariadicAndRest<[a: 0, b: 1, ...c: 2[]]>;
>SubTup2VariadicAndRestTest : [0, 1, 2]

type SubTup2TrailingVariadic<T extends unknown[]> = T extends [
>SubTup2TrailingVariadic : SubTup2TrailingVariadic<T>

...any,
...infer B extends [any, any],
]
? B
: never;

type SubTup2TrailingVariadicTest = SubTup2TrailingVariadic<[...a: 0[], b: 1, c: 2]>;
>SubTup2TrailingVariadicTest : [b: 1, c: 2]

type SubTup2TrailingVariadicTest2 = SubTup2TrailingVariadic<[...a: 0[], b: 1, c: 2, d: 3]>;
>SubTup2TrailingVariadicTest2 : [c: 2, d: 3]

type SubTup2RestAndTrailingVariadic2<T extends unknown[]> = T extends [
>SubTup2RestAndTrailingVariadic2 : SubTup2RestAndTrailingVariadic2<T>

...(infer C)[],
...infer B extends [any, any],
]
? [C, ...B]
: never;

type SubTup2RestAndTrailingVariadic2Test = SubTup2RestAndTrailingVariadic2<[...a: 0[], b: 1, c: 2]>;
>SubTup2RestAndTrailingVariadic2Test : [0, 1, 2]

type SubTup2VariadicWithLeadingFixedElements<T extends unknown[]> = T extends [
>SubTup2VariadicWithLeadingFixedElements : SubTup2VariadicWithLeadingFixedElements<T>

any,
...infer B extends [any, any],
...any
]
? B
: never;

type SubTup2VariadicWithLeadingFixedElementsTest = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, ...d: 3[]]>;
>SubTup2VariadicWithLeadingFixedElementsTest : [b: 1, c: 2]

type SubTup2VariadicWithLeadingFixedElementsTest2 = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, d: 3, ...e: 4[]]>;
>SubTup2VariadicWithLeadingFixedElementsTest2 : [b: 1, c: 2]

type SubTup2TrailingVariadicWithTrailingFixedElements<T extends unknown[]> = T extends [
>SubTup2TrailingVariadicWithTrailingFixedElements : SubTup2TrailingVariadicWithTrailingFixedElements<T>

...any,
...infer B extends [any, any],
any,
]
? B
: never;

type SubTup2TrailingVariadicWithTrailingFixedElementsTest = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: 0[], b: 1, c: 2, d: 3]>;
>SubTup2TrailingVariadicWithTrailingFixedElementsTest : [b: 1, c: 2]

type SubTup2TrailingVariadicWithTrailingFixedElementsTest2 = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: 0[], b: 1, c: 2, d: 3, e: 4]>;
>SubTup2TrailingVariadicWithTrailingFixedElementsTest2 : [c: 2, d: 3]

Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// @strict: true
// @noEmit: true

// repro #51138

type SubTup2FixedLength<T extends unknown[]> = T extends [
...infer B extends [any, any],
any
]
? B
: never;

type SubTup2FixedLengthTest = SubTup2FixedLength<[a: 0, b: 1, c: 2]>;

type SubTup2Variadic<T extends unknown[]> = T extends [
...infer B extends [any, any],
...any
]
? B
: never;

type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: 2[]]>;
type SubTup2VariadicTest2 = SubTup2Variadic<[a: 0, b: 1, c: 2, ...d: 3[]]>;

type SubTup2VariadicAndRest<T extends unknown[]> = T extends [
...infer B extends [any, any],
...(infer C)[]
]
? [...B, ...[C]]
: never;

type SubTup2VariadicAndRestTest = SubTup2VariadicAndRest<[a: 0, b: 1, ...c: 2[]]>;

type SubTup2TrailingVariadic<T extends unknown[]> = T extends [
...any,
...infer B extends [any, any],
]
? B
: never;

type SubTup2TrailingVariadicTest = SubTup2TrailingVariadic<[...a: 0[], b: 1, c: 2]>;
type SubTup2TrailingVariadicTest2 = SubTup2TrailingVariadic<[...a: 0[], b: 1, c: 2, d: 3]>;

type SubTup2RestAndTrailingVariadic2<T extends unknown[]> = T extends [
...(infer C)[],
...infer B extends [any, any],
]
? [C, ...B]
: never;

type SubTup2RestAndTrailingVariadic2Test = SubTup2RestAndTrailingVariadic2<[...a: 0[], b: 1, c: 2]>;

type SubTup2VariadicWithLeadingFixedElements<T extends unknown[]> = T extends [
any,
...infer B extends [any, any],
...any
]
? B
: never;

type SubTup2VariadicWithLeadingFixedElementsTest = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, ...d: 3[]]>;
type SubTup2VariadicWithLeadingFixedElementsTest2 = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, d: 3, ...e: 4[]]>;

type SubTup2TrailingVariadicWithTrailingFixedElements<T extends unknown[]> = T extends [
...any,
...infer B extends [any, any],
any,
]
? B
: never;

type SubTup2TrailingVariadicWithTrailingFixedElementsTest = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: 0[], b: 1, c: 2, d: 3]>;
type SubTup2TrailingVariadicWithTrailingFixedElementsTest2 = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: 0[], b: 1, c: 2, d: 3, e: 4]>;