From 31d1d63fc8a540ec718cfcd0a9c8085733c408eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 3 Jan 2023 19:18:09 +0100 Subject: [PATCH] Infer fixed-size tuples from infer type parameters with extends clauses at variadic positions (#51157) * Infer fixed-size tuples from infer type parameters with extends clauses at variadic positions * Improve the fix to handle tuples with leading variadic elements * Fixed indentation * Infer rest element following a variadic element with a fixed-size constraint * Infer rest element preceding a variadic element with a fixed-size constraint * Rewrite the test to avoid accidental union reductions --- src/compiler/checker.ts | 43 ++++- ...ixedTupleExtendsAtVariadicPosition.symbols | 160 ++++++++++++++++++ ...hFixedTupleExtendsAtVariadicPosition.types | 101 +++++++++++ ...WithFixedTupleExtendsAtVariadicPosition.ts | 73 ++++++++ 4 files changed, 370 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.symbols create mode 100644 tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.types create mode 100644 tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 54ddbb48fe1..4c1ad31d43f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24303,13 +24303,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) { diff --git a/tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.symbols b/tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.symbols new file mode 100644 index 00000000000..6992698a049 --- /dev/null +++ b/tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.symbols @@ -0,0 +1,160 @@ +=== tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts === +// repro #51138 + +type SubTup2FixedLength = 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 [ +>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 [ +>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 [ +>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 [ +>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 [ +>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 [ +>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)) + diff --git a/tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.types b/tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.types new file mode 100644 index 00000000000..41695858348 --- /dev/null +++ b/tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.types @@ -0,0 +1,101 @@ +=== tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts === +// repro #51138 + +type SubTup2FixedLength = T extends [ +>SubTup2FixedLength : SubTup2FixedLength + + ...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 [ +>SubTup2Variadic : SubTup2Variadic + + ...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 [ +>SubTup2VariadicAndRest : SubTup2VariadicAndRest + + ...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 [ +>SubTup2TrailingVariadic : SubTup2TrailingVariadic + + ...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 [ +>SubTup2RestAndTrailingVariadic2 : SubTup2RestAndTrailingVariadic2 + + ...(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 [ +>SubTup2VariadicWithLeadingFixedElements : SubTup2VariadicWithLeadingFixedElements + + 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 [ +>SubTup2TrailingVariadicWithTrailingFixedElements : SubTup2TrailingVariadicWithTrailingFixedElements + + ...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] + diff --git a/tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts b/tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts new file mode 100644 index 00000000000..89e513adaa0 --- /dev/null +++ b/tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts @@ -0,0 +1,73 @@ +// @strict: true +// @noEmit: true + +// repro #51138 + +type SubTup2FixedLength = T extends [ + ...infer B extends [any, any], + any +] + ? B + : never; + +type SubTup2FixedLengthTest = SubTup2FixedLength<[a: 0, b: 1, c: 2]>; + +type SubTup2Variadic = 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 [ + ...infer B extends [any, any], + ...(infer C)[] +] + ? [...B, ...[C]] + : never; + +type SubTup2VariadicAndRestTest = SubTup2VariadicAndRest<[a: 0, b: 1, ...c: 2[]]>; + +type SubTup2TrailingVariadic = 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 [ + ...(infer C)[], + ...infer B extends [any, any], +] + ? [C, ...B] + : never; + +type SubTup2RestAndTrailingVariadic2Test = SubTup2RestAndTrailingVariadic2<[...a: 0[], b: 1, c: 2]>; + +type SubTup2VariadicWithLeadingFixedElements = 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 [ + ...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]>;