From bb14f5399216a9c0d6e7ff5eb336f0ac0cb44abf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 11 Jan 2024 14:26:05 -0800 Subject: [PATCH 1/6] Revise and simplify tuple instantiation logic --- src/compiler/checker.ts | 53 ++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 508f6bb323706..a7b0411e3b680 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19689,11 +19689,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) { return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); } - if (isGenericTupleType(t)) { - return instantiateMappedGenericTupleType(t, type, typeVariable, mapper); - } if (isTupleType(t)) { - return instantiateMappedTupleType(t, type, prependTypeMapping(typeVariable, t, mapper)); + return instantiateMappedTupleType(t, type, typeVariable, mapper); } } return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); @@ -19713,26 +19710,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return modifiers & MappedTypeModifiers.IncludeReadonly ? true : modifiers & MappedTypeModifiers.ExcludeReadonly ? false : state; } - function instantiateMappedGenericTupleType(tupleType: TupleTypeReference, mappedType: MappedType, typeVariable: TypeVariable, mapper: TypeMapper) { - // When a tuple type is generic (i.e. when it contains variadic elements), we want to eagerly map the - // non-generic elements and defer mapping the generic elements. In order to facilitate this, we transform - // M<[A, B?, ...T, ...C[]] into [...M<[A]>, ...M<[B?]>, ...M, ...M] and then rely on tuple type - // normalization to resolve the non-generic parts of the resulting tuple. + function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, typeVariable: TypeVariable, mapper: TypeMapper) { + // We apply the mapped type's template type to each of the fixed part elements. For variadic elements, we + // apply the mapped type itself to the variadic element type. For other elements in the variable part of the + // tuple, we surround the element type with an array type and apply the mapped type to that. This ensures + // that we get sequential property key types ("0", "1", "2", etc.) for the fixed part of the tuple, and + // property key type number for the remaining elements. const elementFlags = tupleType.target.elementFlags; - const elementTypes = map(getElementTypes(tupleType), (t, i) => { - const singleton = elementFlags[i] & ElementFlags.Variadic ? t : - elementFlags[i] & ElementFlags.Rest ? createArrayType(t) : - createTupleType([t], [elementFlags[i]]); - // avoid infinite recursion, if the singleton is the type variable itself - // then we'd just get back here with the same arguments from within instantiateMappedType - if (singleton === typeVariable) { - return mappedType; - } - // The singleton is never a generic tuple type, so it is safe to recurse here. - return instantiateMappedType(mappedType, prependTypeMapping(typeVariable, singleton, mapper)); + const fixedLength = tupleType.target.fixedLength; + const fixedMapper = fixedLength ? prependTypeMapping(typeVariable, tupleType, mapper) : mapper; + const newElementTypes = map(getElementTypes(tupleType), (type, i) => { + const flags = elementFlags[i]; + return i < fixedLength ? instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(flags & ElementFlags.Optional), fixedMapper) : + flags & ElementFlags.Variadic ? instantiateType(mappedType, prependTypeMapping(typeVariable, type, mapper)) : + getElementTypeOfArrayType(instantiateType(mappedType, prependTypeMapping(typeVariable, createArrayType(type), mapper))) || unknownType; }); + const modifiers = getMappedTypeModifiers(mappedType); + const newElementFlags = modifiers & MappedTypeModifiers.IncludeOptional ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) : + modifiers & MappedTypeModifiers.ExcludeOptional ? map(elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) : + elementFlags; const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, getMappedTypeModifiers(mappedType)); - return createTupleType(elementTypes, map(elementTypes, _ => ElementFlags.Variadic), newReadonly); + return contains(newElementTypes, errorType) ? errorType : + createTupleType(newElementTypes, newElementFlags, newReadonly, tupleType.target.labeledElementDeclarations); } function instantiateMappedArrayType(arrayType: Type, mappedType: MappedType, mapper: TypeMapper) { @@ -19741,18 +19740,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { createArrayType(elementType, getModifiedReadonlyState(isReadonlyArrayType(arrayType), getMappedTypeModifiers(mappedType))); } - function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) { - const elementFlags = tupleType.target.elementFlags; - const elementTypes = map(getElementTypes(tupleType), (_, i) => instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(elementFlags[i] & ElementFlags.Optional), mapper)); - const modifiers = getMappedTypeModifiers(mappedType); - const newTupleModifiers = modifiers & MappedTypeModifiers.IncludeOptional ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) : - modifiers & MappedTypeModifiers.ExcludeOptional ? map(elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) : - elementFlags; - const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers); - return contains(elementTypes, errorType) ? errorType : - createTupleType(elementTypes, newTupleModifiers, newReadonly, tupleType.target.labeledElementDeclarations); - } - function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) { const templateMapper = appendTypeMapping(mapper, getTypeParameterFromMappedType(type), key); const propType = instantiateType(getTemplateTypeFromMappedType(type.target as MappedType || type), templateMapper); From d369700617902fc8de01243dcccf77d007dcffb8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 11 Jan 2024 14:27:02 -0800 Subject: [PATCH 2/6] Accept new baselines --- ...neMappedGenericTupleTypeNoCrash.errors.txt | 20 +++++++++++++++++++ ...rInlineMappedGenericTupleTypeNoCrash.types | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.errors.txt diff --git a/tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.errors.txt b/tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.errors.txt new file mode 100644 index 0000000000000..8d568d19a5373 --- /dev/null +++ b/tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.errors.txt @@ -0,0 +1,20 @@ +circularInlineMappedGenericTupleTypeNoCrash.ts(11,12): error TS2589: Type instantiation is excessively deep and possibly infinite. + + +==== circularInlineMappedGenericTupleTypeNoCrash.ts (1 errors) ==== + class Foo { + public readonly elements: { [P in keyof Elements]: { bar: Elements[P] } }; + + public constructor( + ...elements: { [P in keyof Elements]: { bar: Elements[P] } } + ) { + this.elements = elements; + } + + public add(): Foo<[...Elements, "abc"]> { + return new Foo<[...Elements, "abc"]>(...this.elements, { bar: "abc" }); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.types b/tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.types index 638640eeda181..660b3ff1bac7e 100644 --- a/tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.types +++ b/tests/baselines/reference/circularInlineMappedGenericTupleTypeNoCrash.types @@ -32,8 +32,8 @@ class Foo { >this.elements : { [P in keyof Elements]: { bar: Elements[P]; }; } >this : this >elements : { [P in keyof Elements]: { bar: Elements[P]; }; } ->{ bar: "abc" } : { bar: "abc"; } ->bar : "abc" +>{ bar: "abc" } : { bar: string; } +>bar : string >"abc" : "abc" } } From be36e763cd936032c4a9a5aa31987838dfbd0bd3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 11 Jan 2024 14:52:57 -0800 Subject: [PATCH 3/6] Add tests --- .../mappedTypesGenericTuples.symbols | 151 ++++++++++++++++++ .../reference/mappedTypesGenericTuples.types | 90 +++++++++++ .../types/mapped/mappedTypesGenericTuples.ts | 45 ++++++ 3 files changed, 286 insertions(+) create mode 100644 tests/baselines/reference/mappedTypesGenericTuples.symbols create mode 100644 tests/baselines/reference/mappedTypesGenericTuples.types create mode 100644 tests/cases/conformance/types/mapped/mappedTypesGenericTuples.ts diff --git a/tests/baselines/reference/mappedTypesGenericTuples.symbols b/tests/baselines/reference/mappedTypesGenericTuples.symbols new file mode 100644 index 0000000000000..c1dddec4b8e35 --- /dev/null +++ b/tests/baselines/reference/mappedTypesGenericTuples.symbols @@ -0,0 +1,151 @@ +//// [tests/cases/conformance/types/mapped/mappedTypesGenericTuples.ts] //// + +=== mappedTypesGenericTuples.ts === +// Property keys are `number` following the fixed part of a tuple + +type K = { [P in keyof T]: P }; +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 2, 7)) +>P : Symbol(P, Decl(mappedTypesGenericTuples.ts, 2, 15)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 2, 7)) +>P : Symbol(P, Decl(mappedTypesGenericTuples.ts, 2, 15)) + +type M = { [P in keyof T]: T[P] }; +>M : Symbol(M, Decl(mappedTypesGenericTuples.ts, 2, 34)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 3, 7)) +>P : Symbol(P, Decl(mappedTypesGenericTuples.ts, 3, 15)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 3, 7)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 3, 7)) +>P : Symbol(P, Decl(mappedTypesGenericTuples.ts, 3, 15)) + +type KA = K<[string, string, boolean]>; // ["0", "1", "2"] +>KA : Symbol(KA, Decl(mappedTypesGenericTuples.ts, 3, 37)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 0, 0)) + +type KB = K<[string, string, ...string[], string]>; // ["0", "1", ...number[], number] +>KB : Symbol(KB, Decl(mappedTypesGenericTuples.ts, 5, 39)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 0, 0)) + +type KC = K<[...string[]]>; // number[] +>KC : Symbol(KC, Decl(mappedTypesGenericTuples.ts, 6, 51)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 0, 0)) + +type KD = K; // number[] +>KD : Symbol(KD, Decl(mappedTypesGenericTuples.ts, 7, 27)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 0, 0)) + +type A = { a: string }; +>A : Symbol(A, Decl(mappedTypesGenericTuples.ts, 8, 22)) +>a : Symbol(a, Decl(mappedTypesGenericTuples.ts, 10, 10)) + +type B = { b: string }; +>B : Symbol(B, Decl(mappedTypesGenericTuples.ts, 10, 23)) +>b : Symbol(b, Decl(mappedTypesGenericTuples.ts, 11, 10)) + +type C = { c: string }; +>C : Symbol(C, Decl(mappedTypesGenericTuples.ts, 11, 23)) +>c : Symbol(c, Decl(mappedTypesGenericTuples.ts, 12, 10)) + +type D = { d: string }; +>D : Symbol(D, Decl(mappedTypesGenericTuples.ts, 12, 23)) +>d : Symbol(d, Decl(mappedTypesGenericTuples.ts, 13, 10)) + +type V0 = [A, B?, ...T, ...C[]] +>V0 : Symbol(V0, Decl(mappedTypesGenericTuples.ts, 13, 23)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 15, 8)) +>A : Symbol(A, Decl(mappedTypesGenericTuples.ts, 8, 22)) +>B : Symbol(B, Decl(mappedTypesGenericTuples.ts, 10, 23)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 15, 8)) +>C : Symbol(C, Decl(mappedTypesGenericTuples.ts, 11, 23)) + +type V1 = [A, ...T, B, ...C[], D] +>V1 : Symbol(V1, Decl(mappedTypesGenericTuples.ts, 15, 52)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 16, 8)) +>A : Symbol(A, Decl(mappedTypesGenericTuples.ts, 8, 22)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 16, 8)) +>B : Symbol(B, Decl(mappedTypesGenericTuples.ts, 10, 23)) +>C : Symbol(C, Decl(mappedTypesGenericTuples.ts, 11, 23)) +>D : Symbol(D, Decl(mappedTypesGenericTuples.ts, 12, 23)) + +type K0 = K>; // ["0", "1"?, ...K, ...number[]] +>K0 : Symbol(K0, Decl(mappedTypesGenericTuples.ts, 16, 54)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 18, 8)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 0, 0)) +>V0 : Symbol(V0, Decl(mappedTypesGenericTuples.ts, 13, 23)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 18, 8)) + +type K1 = K>; // ["0", ...K, number, ...number[], number] +>K1 : Symbol(K1, Decl(mappedTypesGenericTuples.ts, 18, 40)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 19, 8)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 0, 0)) +>V1 : Symbol(V1, Decl(mappedTypesGenericTuples.ts, 15, 52)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 19, 8)) + +type M0 = M>; // [A, B?, ...M, ...C[]] +>M0 : Symbol(M0, Decl(mappedTypesGenericTuples.ts, 19, 40)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 21, 8)) +>M : Symbol(M, Decl(mappedTypesGenericTuples.ts, 2, 34)) +>V0 : Symbol(V0, Decl(mappedTypesGenericTuples.ts, 13, 23)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 21, 8)) + +type M1 = M>; // [A, ...M, B, ...C[], D] +>M1 : Symbol(M1, Decl(mappedTypesGenericTuples.ts, 21, 40)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 22, 8)) +>M : Symbol(M, Decl(mappedTypesGenericTuples.ts, 2, 34)) +>V1 : Symbol(V1, Decl(mappedTypesGenericTuples.ts, 15, 52)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 22, 8)) + +// Repro from #48856 + +type Keys = { [K in keyof O]: K }; +>Keys : Symbol(Keys, Decl(mappedTypesGenericTuples.ts, 22, 40)) +>O : Symbol(O, Decl(mappedTypesGenericTuples.ts, 26, 10)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 26, 36)) +>O : Symbol(O, Decl(mappedTypesGenericTuples.ts, 26, 10)) +>K : Symbol(K, Decl(mappedTypesGenericTuples.ts, 26, 36)) + +type Keys1 = Keys<[string, ...string[]]>; +>Keys1 : Symbol(Keys1, Decl(mappedTypesGenericTuples.ts, 26, 55)) +>Keys : Symbol(Keys, Decl(mappedTypesGenericTuples.ts, 22, 40)) + +type Keys2 = Keys<[string, ...string[], number]>; +>Keys2 : Symbol(Keys2, Decl(mappedTypesGenericTuples.ts, 28, 41)) +>Keys : Symbol(Keys, Decl(mappedTypesGenericTuples.ts, 22, 40)) + +// Repro from #56888 + +type T1 = ['a', 'b', 'c'] extends readonly [infer H, ...unknown[]] ? H : never; // "a" +>T1 : Symbol(T1, Decl(mappedTypesGenericTuples.ts, 29, 49)) +>H : Symbol(H, Decl(mappedTypesGenericTuples.ts, 33, 49)) +>H : Symbol(H, Decl(mappedTypesGenericTuples.ts, 33, 49)) + +type T2 = ['a', 'b', 'c'] extends Readonly<[infer H, ...unknown[]]> ? H : never; // "a" +>T2 : Symbol(T2, Decl(mappedTypesGenericTuples.ts, 33, 79)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>H : Symbol(H, Decl(mappedTypesGenericTuples.ts, 34, 49)) +>H : Symbol(H, Decl(mappedTypesGenericTuples.ts, 34, 49)) + +type T3 = ['a', 'b', 'c'] extends readonly [...unknown[], infer L] ? L : never; // "c" +>T3 : Symbol(T3, Decl(mappedTypesGenericTuples.ts, 34, 80)) +>L : Symbol(L, Decl(mappedTypesGenericTuples.ts, 35, 63)) +>L : Symbol(L, Decl(mappedTypesGenericTuples.ts, 35, 63)) + +type T4 = ['a', 'b', 'c'] extends Readonly<[...unknown[], infer L]> ? L : never; // "c" +>T4 : Symbol(T4, Decl(mappedTypesGenericTuples.ts, 35, 79)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>L : Symbol(L, Decl(mappedTypesGenericTuples.ts, 36, 63)) +>L : Symbol(L, Decl(mappedTypesGenericTuples.ts, 36, 63)) + +// Repro from #56888 + +type R1 = readonly [...unknown[], T]; // readonly [...unknown[], T] +>R1 : Symbol(R1, Decl(mappedTypesGenericTuples.ts, 36, 80)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 40, 8)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 40, 8)) + +type R2 = Readonly<[...unknown[], T]>; // readonly [...unknown[], T] +>R2 : Symbol(R2, Decl(mappedTypesGenericTuples.ts, 40, 40)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 41, 8)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypesGenericTuples.ts, 41, 8)) + diff --git a/tests/baselines/reference/mappedTypesGenericTuples.types b/tests/baselines/reference/mappedTypesGenericTuples.types new file mode 100644 index 0000000000000..65814e87dcbd2 --- /dev/null +++ b/tests/baselines/reference/mappedTypesGenericTuples.types @@ -0,0 +1,90 @@ +//// [tests/cases/conformance/types/mapped/mappedTypesGenericTuples.ts] //// + +=== mappedTypesGenericTuples.ts === +// Property keys are `number` following the fixed part of a tuple + +type K = { [P in keyof T]: P }; +>K : K + +type M = { [P in keyof T]: T[P] }; +>M : M + +type KA = K<[string, string, boolean]>; // ["0", "1", "2"] +>KA : ["0", "1", "2"] + +type KB = K<[string, string, ...string[], string]>; // ["0", "1", ...number[], number] +>KB : ["0", "1", ...number[], number] + +type KC = K<[...string[]]>; // number[] +>KC : number[] + +type KD = K; // number[] +>KD : number[] + +type A = { a: string }; +>A : { a: string; } +>a : string + +type B = { b: string }; +>B : { b: string; } +>b : string + +type C = { c: string }; +>C : { c: string; } +>c : string + +type D = { d: string }; +>D : { d: string; } +>d : string + +type V0 = [A, B?, ...T, ...C[]] +>V0 : [A, (B | undefined)?, ...T, ...C[]] + +type V1 = [A, ...T, B, ...C[], D] +>V1 : [A, ...T, B, ...C[], D] + +type K0 = K>; // ["0", "1"?, ...K, ...number[]] +>K0 : ["0", ("1" | undefined)?, ...K, ...number[]] + +type K1 = K>; // ["0", ...K, number, ...number[], number] +>K1 : ["0", ...K, number, ...number[], number] + +type M0 = M>; // [A, B?, ...M, ...C[]] +>M0 : [A, (B | undefined)?, ...M, ...C[]] + +type M1 = M>; // [A, ...M, B, ...C[], D] +>M1 : [A, ...M, B, ...C[], D] + +// Repro from #48856 + +type Keys = { [K in keyof O]: K }; +>Keys : Keys + +type Keys1 = Keys<[string, ...string[]]>; +>Keys1 : ["0", ...number[]] + +type Keys2 = Keys<[string, ...string[], number]>; +>Keys2 : ["0", ...number[], number] + +// Repro from #56888 + +type T1 = ['a', 'b', 'c'] extends readonly [infer H, ...unknown[]] ? H : never; // "a" +>T1 : "a" + +type T2 = ['a', 'b', 'c'] extends Readonly<[infer H, ...unknown[]]> ? H : never; // "a" +>T2 : "a" + +type T3 = ['a', 'b', 'c'] extends readonly [...unknown[], infer L] ? L : never; // "c" +>T3 : "c" + +type T4 = ['a', 'b', 'c'] extends Readonly<[...unknown[], infer L]> ? L : never; // "c" +>T4 : "c" + +// Repro from #56888 + +type R1 = readonly [...unknown[], T]; // readonly [...unknown[], T] +>R1 : R1 + +type R2 = Readonly<[...unknown[], T]>; // readonly [...unknown[], T] +>R2 : readonly [...unknown[], T] + diff --git a/tests/cases/conformance/types/mapped/mappedTypesGenericTuples.ts b/tests/cases/conformance/types/mapped/mappedTypesGenericTuples.ts new file mode 100644 index 0000000000000..0eee074118c00 --- /dev/null +++ b/tests/cases/conformance/types/mapped/mappedTypesGenericTuples.ts @@ -0,0 +1,45 @@ +// @strict: true +// @noEmit: true + +// Property keys are `number` following the fixed part of a tuple + +type K = { [P in keyof T]: P }; +type M = { [P in keyof T]: T[P] }; + +type KA = K<[string, string, boolean]>; // ["0", "1", "2"] +type KB = K<[string, string, ...string[], string]>; // ["0", "1", ...number[], number] +type KC = K<[...string[]]>; // number[] +type KD = K; // number[] + +type A = { a: string }; +type B = { b: string }; +type C = { c: string }; +type D = { d: string }; + +type V0 = [A, B?, ...T, ...C[]] +type V1 = [A, ...T, B, ...C[], D] + +type K0 = K>; // ["0", "1"?, ...K, ...number[]] +type K1 = K>; // ["0", ...K, number, ...number[], number] + +type M0 = M>; // [A, B?, ...M, ...C[]] +type M1 = M>; // [A, ...M, B, ...C[], D] + +// Repro from #48856 + +type Keys = { [K in keyof O]: K }; + +type Keys1 = Keys<[string, ...string[]]>; +type Keys2 = Keys<[string, ...string[], number]>; + +// Repro from #56888 + +type T1 = ['a', 'b', 'c'] extends readonly [infer H, ...unknown[]] ? H : never; // "a" +type T2 = ['a', 'b', 'c'] extends Readonly<[infer H, ...unknown[]]> ? H : never; // "a" +type T3 = ['a', 'b', 'c'] extends readonly [...unknown[], infer L] ? L : never; // "c" +type T4 = ['a', 'b', 'c'] extends Readonly<[...unknown[], infer L]> ? L : never; // "c" + +// Repro from #56888 + +type R1 = readonly [...unknown[], T]; // readonly [...unknown[], T] +type R2 = Readonly<[...unknown[], T]>; // readonly [...unknown[], T] From af142b36ef6923663b4b0fd0cad4a6eeb628256d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 12 Jan 2024 08:16:22 -0800 Subject: [PATCH 4/6] Address CR feedback --- src/compiler/checker.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 467bf9dbe2092..93cea7c12258d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19770,8 +19770,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We apply the mapped type's template type to each of the fixed part elements. For variadic elements, we // apply the mapped type itself to the variadic element type. For other elements in the variable part of the // tuple, we surround the element type with an array type and apply the mapped type to that. This ensures - // that we get sequential property key types ("0", "1", "2", etc.) for the fixed part of the tuple, and - // property key type number for the remaining elements. + // that we get sequential property key types for the fixed part of the tuple, and property key type number + // for the remaining elements. For example + // + // type Keys = { [K in keyof T]: K }; + // type Foo = Keys<[string, string, ...T, string]>; // ["0", "1", ...Keys, number] + // const elementFlags = tupleType.target.elementFlags; const fixedLength = tupleType.target.fixedLength; const fixedMapper = fixedLength ? prependTypeMapping(typeVariable, tupleType, mapper) : mapper; @@ -19779,7 +19783,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const flags = elementFlags[i]; return i < fixedLength ? instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(flags & ElementFlags.Optional), fixedMapper) : flags & ElementFlags.Variadic ? instantiateType(mappedType, prependTypeMapping(typeVariable, type, mapper)) : - getElementTypeOfArrayType(instantiateType(mappedType, prependTypeMapping(typeVariable, createArrayType(type), mapper))) || unknownType; + getElementTypeOfArrayType(instantiateType(mappedType, prependTypeMapping(typeVariable, createArrayType(type), mapper))) ?? unknownType; }); const modifiers = getMappedTypeModifiers(mappedType); const newElementFlags = modifiers & MappedTypeModifiers.IncludeOptional ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) : From 70715eae3ba4ded0ea7f4f0b3792aeae35944c8f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 12 Jan 2024 08:56:44 -0800 Subject: [PATCH 5/6] Fix rest element error reporting --- src/compiler/checker.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 93cea7c12258d..50ed79b9e47ef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -40412,11 +40412,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkTupleType(node: TupleTypeNode) { - const elementTypes = node.elements; let seenOptionalElement = false; let seenRestElement = false; - for (const e of elementTypes) { - const flags = getTupleElementFlags(e); + for (const e of node.elements) { + let flags = getTupleElementFlags(e); if (flags & ElementFlags.Variadic) { const type = getTypeFromTypeNode((e as RestTypeNode | NamedTupleMember).type); if (!isArrayLikeType(type)) { @@ -40424,10 +40423,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; } if (isArrayType(type) || isTupleType(type) && type.target.combinedFlags & ElementFlags.Rest) { - seenRestElement = true; + flags |= ElementFlags.Rest; } } - else if (flags & ElementFlags.Rest) { + if (flags & ElementFlags.Rest) { if (seenRestElement) { grammarErrorOnNode(e, Diagnostics.A_rest_element_cannot_follow_another_rest_element); break; @@ -40441,7 +40440,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } seenOptionalElement = true; } - else if (seenOptionalElement) { + else if (flags & ElementFlags.Required && seenOptionalElement) { grammarErrorOnNode(e, Diagnostics.A_required_element_cannot_follow_an_optional_element); break; } From abc9c43b18879958772650f4a1bce4b2a34b718a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 12 Jan 2024 09:00:26 -0800 Subject: [PATCH 6/6] Add tests --- .../reference/variadicTuples2.errors.txt | 71 ++-- tests/baselines/reference/variadicTuples2.js | 9 + .../reference/variadicTuples2.symbols | 394 +++++++++--------- .../baselines/reference/variadicTuples2.types | 12 + .../types/tuple/variadicTuples2.ts | 5 + 5 files changed, 275 insertions(+), 216 deletions(-) diff --git a/tests/baselines/reference/variadicTuples2.errors.txt b/tests/baselines/reference/variadicTuples2.errors.txt index 4539265d4bff6..9ae0ed7c394e3 100644 --- a/tests/baselines/reference/variadicTuples2.errors.txt +++ b/tests/baselines/reference/variadicTuples2.errors.txt @@ -1,71 +1,75 @@ variadicTuples2.ts(7,34): error TS1265: A rest element cannot follow another rest element. variadicTuples2.ts(8,34): error TS1266: An optional element cannot follow a rest element. variadicTuples2.ts(9,30): error TS1257: A required element cannot follow an optional element. -variadicTuples2.ts(42,1): error TS2322: Type '[string, string, number, number]' is not assignable to type '[...string[], number]'. +variadicTuples2.ts(11,26): error TS1265: A rest element cannot follow another rest element. +variadicTuples2.ts(12,26): error TS1265: A rest element cannot follow another rest element. +variadicTuples2.ts(13,31): error TS1265: A rest element cannot follow another rest element. +variadicTuples2.ts(14,31): error TS1265: A rest element cannot follow another rest element. +variadicTuples2.ts(47,1): error TS2322: Type '[string, string, number, number]' is not assignable to type '[...string[], number]'. Type at positions 0 through 2 in source is not compatible with type at position 0 in target. Type 'number' is not assignable to type 'string'. -variadicTuples2.ts(48,5): error TS2345: Argument of type '["abc", "def", 5, 6]' is not assignable to parameter of type '[...strs: string[], num: number]'. +variadicTuples2.ts(53,5): error TS2345: Argument of type '["abc", "def", 5, 6]' is not assignable to parameter of type '[...strs: string[], num: number]'. Type at positions 0 through 2 in source is not compatible with type at position 0 in target. Type 'number' is not assignable to type 'string'. -variadicTuples2.ts(51,1): error TS2322: Type '[number]' is not assignable to type '[number, ...string[], number]'. +variadicTuples2.ts(56,1): error TS2322: Type '[number]' is not assignable to type '[number, ...string[], number]'. Source has 1 element(s) but target requires 2. -variadicTuples2.ts(53,1): error TS2322: Type '[number, number, number]' is not assignable to type '[number, ...string[], number]'. +variadicTuples2.ts(58,1): error TS2322: Type '[number, number, number]' is not assignable to type '[number, ...string[], number]'. Type at position 1 in source is not compatible with type at position 1 in target. Type 'number' is not assignable to type 'string'. -variadicTuples2.ts(56,1): error TS2322: Type '[number, string, number, string]' is not assignable to type '[number, ...string[], number]'. +variadicTuples2.ts(61,1): error TS2322: Type '[number, string, number, string]' is not assignable to type '[number, ...string[], number]'. Type at positions 1 through 2 in source is not compatible with type at position 1 in target. Type 'number' is not assignable to type 'string'. -variadicTuples2.ts(57,8): error TS2322: Type 'boolean' is not assignable to type 'number'. -variadicTuples2.ts(58,1): error TS2322: Type '[number, string, string, boolean]' is not assignable to type '[number, ...string[], number]'. +variadicTuples2.ts(62,8): error TS2322: Type 'boolean' is not assignable to type 'number'. +variadicTuples2.ts(63,1): error TS2322: Type '[number, string, string, boolean]' is not assignable to type '[number, ...string[], number]'. Type at position 3 in source is not compatible with type at position 2 in target. Type 'boolean' is not assignable to type 'number'. -variadicTuples2.ts(61,1): error TS2345: Argument of type '[]' is not assignable to parameter of type '[...strs: string[], n2: number]'. +variadicTuples2.ts(66,1): error TS2345: Argument of type '[]' is not assignable to parameter of type '[...strs: string[], n2: number]'. Source has 0 element(s) but target requires 1. -variadicTuples2.ts(63,8): error TS2345: Argument of type '[1, 2]' is not assignable to parameter of type '[...strs: string[], n2: number]'. +variadicTuples2.ts(68,8): error TS2345: Argument of type '[1, 2]' is not assignable to parameter of type '[...strs: string[], n2: number]'. Type at position 0 in source is not compatible with type at position 0 in target. Type 'number' is not assignable to type 'string'. -variadicTuples2.ts(66,8): error TS2345: Argument of type '["abc", 1, "def"]' is not assignable to parameter of type '[...strs: string[], n2: number]'. +variadicTuples2.ts(71,8): error TS2345: Argument of type '["abc", 1, "def"]' is not assignable to parameter of type '[...strs: string[], n2: number]'. Type at positions 0 through 1 in source is not compatible with type at position 0 in target. Type 'number' is not assignable to type 'string'. -variadicTuples2.ts(67,5): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number'. -variadicTuples2.ts(68,8): error TS2345: Argument of type '["abc", "def", true]' is not assignable to parameter of type '[...strs: string[], n2: number]'. +variadicTuples2.ts(72,5): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number'. +variadicTuples2.ts(73,8): error TS2345: Argument of type '["abc", "def", true]' is not assignable to parameter of type '[...strs: string[], n2: number]'. Type at position 2 in source is not compatible with type at position 1 in target. Type 'boolean' is not assignable to type 'number'. -variadicTuples2.ts(71,5): error TS2322: Type '[number, number]' is not assignable to type '[number, ...T]'. +variadicTuples2.ts(76,5): error TS2322: Type '[number, number]' is not assignable to type '[number, ...T]'. Source provides no match for variadic element at position 1 in target. -variadicTuples2.ts(72,5): error TS2322: Type '[number, ...number[]]' is not assignable to type '[number, ...T]'. +variadicTuples2.ts(77,5): error TS2322: Type '[number, ...number[]]' is not assignable to type '[number, ...T]'. Target requires 2 element(s) but source may have fewer. -variadicTuples2.ts(73,5): error TS2322: Type '[number, ...T]' is not assignable to type '[number, number]'. +variadicTuples2.ts(78,5): error TS2322: Type '[number, ...T]' is not assignable to type '[number, number]'. Type '[number, ...unknown[]]' is not assignable to type '[number, number]'. Target requires 2 element(s) but source may have fewer. -variadicTuples2.ts(74,5): error TS2322: Type '[number, ...T]' is not assignable to type '[number, ...number[]]'. +variadicTuples2.ts(79,5): error TS2322: Type '[number, ...T]' is not assignable to type '[number, ...number[]]'. Type '[number, ...unknown[]]' is not assignable to type '[number, ...number[]]'. Type at position 1 in source is not compatible with type at position 1 in target. Type 'unknown' is not assignable to type 'number'. -variadicTuples2.ts(79,5): error TS2322: Type '[number, string, ...any[]]' is not assignable to type '[number, ...number[]]'. +variadicTuples2.ts(84,5): error TS2322: Type '[number, string, ...any[]]' is not assignable to type '[number, ...number[]]'. Type at positions 1 through 2 in source is not compatible with type at position 1 in target. Type 'string' is not assignable to type 'number'. -variadicTuples2.ts(111,16): error TS2345: Argument of type '[1, 2, 3, number]' is not assignable to parameter of type '[...number[], (...values: number[]) => void]'. +variadicTuples2.ts(116,16): error TS2345: Argument of type '[1, 2, 3, number]' is not assignable to parameter of type '[...number[], (...values: number[]) => void]'. Type at position 3 in source is not compatible with type at position 1 in target. Type 'number' is not assignable to type '(...values: number[]) => void'. -variadicTuples2.ts(112,6): error TS2345: Argument of type 'string[]' is not assignable to parameter of type '[...string[], (...values: string[]) => void]'. +variadicTuples2.ts(117,6): error TS2345: Argument of type 'string[]' is not assignable to parameter of type '[...string[], (...values: string[]) => void]'. Source provides no match for required element at position 1 in target. -variadicTuples2.ts(115,5): error TS2345: Argument of type '[]' is not assignable to parameter of type '[...unknown[], unknown, unknown]'. +variadicTuples2.ts(120,5): error TS2345: Argument of type '[]' is not assignable to parameter of type '[...unknown[], unknown, unknown]'. Source has 0 element(s) but target requires 2. -variadicTuples2.ts(116,5): error TS2345: Argument of type '[number]' is not assignable to parameter of type '[...unknown[], unknown, unknown]'. +variadicTuples2.ts(121,5): error TS2345: Argument of type '[number]' is not assignable to parameter of type '[...unknown[], unknown, unknown]'. Source has 1 element(s) but target requires 2. -variadicTuples2.ts(121,5): error TS2345: Argument of type '[]' is not assignable to parameter of type '[unknown, ...unknown[], unknown]'. +variadicTuples2.ts(126,5): error TS2345: Argument of type '[]' is not assignable to parameter of type '[unknown, ...unknown[], unknown]'. Source has 0 element(s) but target requires 2. -variadicTuples2.ts(122,5): error TS2345: Argument of type '[number]' is not assignable to parameter of type '[unknown, ...unknown[], unknown]'. +variadicTuples2.ts(127,5): error TS2345: Argument of type '[number]' is not assignable to parameter of type '[unknown, ...unknown[], unknown]'. Source has 1 element(s) but target requires 2. -variadicTuples2.ts(132,16): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. -variadicTuples2.ts(133,16): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. -variadicTuples2.ts(134,25): error TS2345: Argument of type '["blah2", 1, 2, 3]' is not assignable to parameter of type '[...string[], number]'. +variadicTuples2.ts(137,16): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +variadicTuples2.ts(138,16): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +variadicTuples2.ts(139,25): error TS2345: Argument of type '["blah2", 1, 2, 3]' is not assignable to parameter of type '[...string[], number]'. Type at positions 0 through 2 in source is not compatible with type at position 0 in target. Type 'number' is not assignable to type 'string'. -==== variadicTuples2.ts (29 errors) ==== +==== variadicTuples2.ts (33 errors) ==== // Declarations type V00 = [number, ...string[]]; @@ -82,6 +86,19 @@ variadicTuples2.ts(134,25): error TS2345: Argument of type '["blah2", 1, 2, 3]' ~~~~~~~ !!! error TS1257: A required element cannot follow an optional element. + type V15 = [...string[], ...number[]]; // Error + ~~~~~~~~~~~ +!!! error TS1265: A rest element cannot follow another rest element. + type V16 = [...string[], ...Array]; // Error + ~~~~~~~~~~~~~~~~ +!!! error TS1265: A rest element cannot follow another rest element. + type V17 = [...Array, ...number[]]; // Error + ~~~~~~~~~~~ +!!! error TS1265: A rest element cannot follow another rest element. + type V18 = [...Array, ...Array]; // Error + ~~~~~~~~~~~~~~~~ +!!! error TS1265: A rest element cannot follow another rest element. + // Normalization type Tup3 = [...T, ...U, ...V]; diff --git a/tests/baselines/reference/variadicTuples2.js b/tests/baselines/reference/variadicTuples2.js index 8b0d2b25a180a..cc48b28f06fed 100644 --- a/tests/baselines/reference/variadicTuples2.js +++ b/tests/baselines/reference/variadicTuples2.js @@ -11,6 +11,11 @@ type V10 = [number, ...string[], ...boolean[]]; // Error type V11 = [number, ...string[], boolean?]; // Error type V12 = [number, string?, boolean]; // Error +type V15 = [...string[], ...number[]]; // Error +type V16 = [...string[], ...Array]; // Error +type V17 = [...Array, ...number[]]; // Error +type V18 = [...Array, ...Array]; // Error + // Normalization type Tup3 = [...T, ...U, ...V]; @@ -242,6 +247,10 @@ type V03 = [number, ...string[], number]; type V10 = [number, ...string[], ...boolean[]]; type V11 = [number, ...string[], boolean?]; type V12 = [number, string?, boolean]; +type V15 = [...string[], ...number[]]; +type V16 = [...string[], ...Array]; +type V17 = [...Array, ...number[]]; +type V18 = [...Array, ...Array]; type Tup3 = [...T, ...U, ...V]; type V20 = Tup3<[number], string[], [number]>; type V21 = Tup3<[number], [string?], [boolean]>; diff --git a/tests/baselines/reference/variadicTuples2.symbols b/tests/baselines/reference/variadicTuples2.symbols index 852bdf904f8c9..37a32b9b3db5d 100644 --- a/tests/baselines/reference/variadicTuples2.symbols +++ b/tests/baselines/reference/variadicTuples2.symbols @@ -21,394 +21,410 @@ type V11 = [number, ...string[], boolean?]; // Error type V12 = [number, string?, boolean]; // Error >V12 : Symbol(V12, Decl(variadicTuples2.ts, 7, 43)) +type V15 = [...string[], ...number[]]; // Error +>V15 : Symbol(V15, Decl(variadicTuples2.ts, 8, 38)) + +type V16 = [...string[], ...Array]; // Error +>V16 : Symbol(V16, Decl(variadicTuples2.ts, 10, 38)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +type V17 = [...Array, ...number[]]; // Error +>V17 : Symbol(V17, Decl(variadicTuples2.ts, 11, 43)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +type V18 = [...Array, ...Array]; // Error +>V18 : Symbol(V18, Decl(variadicTuples2.ts, 12, 43)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + // Normalization type Tup3 = [...T, ...U, ...V]; ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->T : Symbol(T, Decl(variadicTuples2.ts, 12, 10)) ->U : Symbol(U, Decl(variadicTuples2.ts, 12, 30)) ->V : Symbol(V, Decl(variadicTuples2.ts, 12, 51)) ->T : Symbol(T, Decl(variadicTuples2.ts, 12, 10)) ->U : Symbol(U, Decl(variadicTuples2.ts, 12, 30)) ->V : Symbol(V, Decl(variadicTuples2.ts, 12, 51)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>T : Symbol(T, Decl(variadicTuples2.ts, 17, 10)) +>U : Symbol(U, Decl(variadicTuples2.ts, 17, 30)) +>V : Symbol(V, Decl(variadicTuples2.ts, 17, 51)) +>T : Symbol(T, Decl(variadicTuples2.ts, 17, 10)) +>U : Symbol(U, Decl(variadicTuples2.ts, 17, 30)) +>V : Symbol(V, Decl(variadicTuples2.ts, 17, 51)) type V20 = Tup3<[number], string[], [number]>; // [number, ...string[], number] ->V20 : Symbol(V20, Decl(variadicTuples2.ts, 12, 94)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V20 : Symbol(V20, Decl(variadicTuples2.ts, 17, 94)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V21 = Tup3<[number], [string?], [boolean]>; // [number, string | undefined, boolean] ->V21 : Symbol(V21, Decl(variadicTuples2.ts, 14, 46)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V21 : Symbol(V21, Decl(variadicTuples2.ts, 19, 46)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V22 = Tup3<[number], string[], boolean[]>; // [number, (string | boolean)[]] ->V22 : Symbol(V22, Decl(variadicTuples2.ts, 15, 48)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V22 : Symbol(V22, Decl(variadicTuples2.ts, 20, 48)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V23 = Tup3<[number], string[], [boolean?]>; // [number, (string | boolean | undefined)[]] ->V23 : Symbol(V23, Decl(variadicTuples2.ts, 16, 47)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V23 : Symbol(V23, Decl(variadicTuples2.ts, 21, 47)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V24 = Tup3<[number], [boolean?], string[]>; // [number, boolean?, ...string[]] ->V24 : Symbol(V24, Decl(variadicTuples2.ts, 17, 48)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V24 : Symbol(V24, Decl(variadicTuples2.ts, 22, 48)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V25 = Tup3; // (string | number | boolean)[] ->V25 : Symbol(V25, Decl(variadicTuples2.ts, 18, 48)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V25 : Symbol(V25, Decl(variadicTuples2.ts, 23, 48)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V26 = Tup3; // [...(string | number)[], boolean] ->V26 : Symbol(V26, Decl(variadicTuples2.ts, 19, 47)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V26 : Symbol(V26, Decl(variadicTuples2.ts, 24, 47)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V27 = Tup3<[number?], [string], [boolean?]>; // [number | undefined, string, boolean?] ->V27 : Symbol(V27, Decl(variadicTuples2.ts, 20, 47)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) +>V27 : Symbol(V27, Decl(variadicTuples2.ts, 25, 47)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) type V30 = Tup3; // [...A, ...(string | number)[]] ->V30 : Symbol(V30, Decl(variadicTuples2.ts, 21, 49)) ->A : Symbol(A, Decl(variadicTuples2.ts, 23, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 23, 9)) +>V30 : Symbol(V30, Decl(variadicTuples2.ts, 26, 49)) +>A : Symbol(A, Decl(variadicTuples2.ts, 28, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 28, 9)) type V31 = Tup3; // (string | number | A[number])[] ->V31 : Symbol(V31, Decl(variadicTuples2.ts, 23, 60)) ->A : Symbol(A, Decl(variadicTuples2.ts, 24, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 24, 9)) +>V31 : Symbol(V31, Decl(variadicTuples2.ts, 28, 60)) +>A : Symbol(A, Decl(variadicTuples2.ts, 29, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 29, 9)) type V32 = Tup3; // [...(string | number)[], ...A] ->V32 : Symbol(V32, Decl(variadicTuples2.ts, 24, 60)) ->A : Symbol(A, Decl(variadicTuples2.ts, 25, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 25, 9)) +>V32 : Symbol(V32, Decl(variadicTuples2.ts, 29, 60)) +>A : Symbol(A, Decl(variadicTuples2.ts, 30, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 30, 9)) type V40 = Tup3; // [...A, string?, ...number[]] ->V40 : Symbol(V40, Decl(variadicTuples2.ts, 25, 60)) ->A : Symbol(A, Decl(variadicTuples2.ts, 27, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 27, 9)) +>V40 : Symbol(V40, Decl(variadicTuples2.ts, 30, 60)) +>A : Symbol(A, Decl(variadicTuples2.ts, 32, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 32, 9)) type V41 = Tup3<[string?], A, number[]>; // [string?, ...A, ...number[]] ->V41 : Symbol(V41, Decl(variadicTuples2.ts, 27, 61)) ->A : Symbol(A, Decl(variadicTuples2.ts, 28, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 28, 9)) +>V41 : Symbol(V41, Decl(variadicTuples2.ts, 32, 61)) +>A : Symbol(A, Decl(variadicTuples2.ts, 33, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 33, 9)) type V42 = Tup3<[string?], number[], A>; // [string?, ...number[], ...A] ->V42 : Symbol(V42, Decl(variadicTuples2.ts, 28, 61)) ->A : Symbol(A, Decl(variadicTuples2.ts, 29, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 29, 9)) +>V42 : Symbol(V42, Decl(variadicTuples2.ts, 33, 61)) +>A : Symbol(A, Decl(variadicTuples2.ts, 34, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 34, 9)) type V50 = Tup3; // [...A, ...(string | number | undefined)[]] ->V50 : Symbol(V50, Decl(variadicTuples2.ts, 29, 61)) ->A : Symbol(A, Decl(variadicTuples2.ts, 31, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 31, 9)) +>V50 : Symbol(V50, Decl(variadicTuples2.ts, 34, 61)) +>A : Symbol(A, Decl(variadicTuples2.ts, 36, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 36, 9)) type V51 = Tup3; // (string | number | A[number] | undefined)[] ->V51 : Symbol(V51, Decl(variadicTuples2.ts, 31, 61)) ->A : Symbol(A, Decl(variadicTuples2.ts, 32, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 32, 9)) +>V51 : Symbol(V51, Decl(variadicTuples2.ts, 36, 61)) +>A : Symbol(A, Decl(variadicTuples2.ts, 37, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 37, 9)) type V52 = Tup3; // [...(string | number | undefined)[], ...A] ->V52 : Symbol(V52, Decl(variadicTuples2.ts, 32, 61)) ->A : Symbol(A, Decl(variadicTuples2.ts, 33, 9)) ->Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 8, 38)) ->A : Symbol(A, Decl(variadicTuples2.ts, 33, 9)) +>V52 : Symbol(V52, Decl(variadicTuples2.ts, 37, 61)) +>A : Symbol(A, Decl(variadicTuples2.ts, 38, 9)) +>Tup3 : Symbol(Tup3, Decl(variadicTuples2.ts, 13, 48)) +>A : Symbol(A, Decl(variadicTuples2.ts, 38, 9)) // Assignability declare let tt1: [...string[], number]; ->tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 37, 11)) +>tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 42, 11)) tt1 = [5]; ->tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 37, 11)) +>tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 42, 11)) tt1 = ['abc', 5]; ->tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 37, 11)) +>tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 42, 11)) tt1 = ['abc', 'def', 5]; ->tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 37, 11)) +>tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 42, 11)) tt1 = ['abc', 'def', 5, 6]; // Error ->tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 37, 11)) +>tt1 : Symbol(tt1, Decl(variadicTuples2.ts, 42, 11)) declare function ft1(...args: [...strs: string[], num: number]): void; ->ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 41, 27)) ->args : Symbol(args, Decl(variadicTuples2.ts, 43, 21)) +>ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 46, 27)) +>args : Symbol(args, Decl(variadicTuples2.ts, 48, 21)) ft1(5); ->ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 41, 27)) +>ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 46, 27)) ft1('abc', 5); ->ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 41, 27)) +>ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 46, 27)) ft1('abc', 'def', 5); ->ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 41, 27)) +>ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 46, 27)) ft1('abc', 'def', 5, 6); // Error ->ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 41, 27)) +>ft1 : Symbol(ft1, Decl(variadicTuples2.ts, 46, 27)) declare let tt2: [number, ...string[], number]; ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [0]; // Error ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [0, 1]; ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [0, 1, 2]; // Error ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [0, 'abc', 1]; ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [0, 'abc', 'def', 1]; ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [0, 'abc', 1, 'def']; // Error ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [true, 'abc', 'def', 1]; // Error ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) tt2 = [0, 'abc', 'def', true]; // Error ->tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 49, 11)) +>tt2 : Symbol(tt2, Decl(variadicTuples2.ts, 54, 11)) declare function ft2(n1: number, ...rest: [...strs: string[], n2: number]): void; ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) ->n1 : Symbol(n1, Decl(variadicTuples2.ts, 59, 21)) ->rest : Symbol(rest, Decl(variadicTuples2.ts, 59, 32)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) +>n1 : Symbol(n1, Decl(variadicTuples2.ts, 64, 21)) +>rest : Symbol(rest, Decl(variadicTuples2.ts, 64, 32)) ft2(0); // Error ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) ft2(0, 1); ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) ft2(0, 1, 2); // Error ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) ft2(0, 'abc', 1); ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) ft2(0, 'abc', 'def', 1); ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) ft2(0, 'abc', 1, 'def'); // Error ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) ft2(true, 'abc', 'def', 1); // Error ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) ft2(0, 'abc', 'def', true); // Error ->ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 57, 30)) +>ft2 : Symbol(ft2, Decl(variadicTuples2.ts, 62, 30)) function ft3(x: [number, ...T], y: [number, number], z: [number, ...number[]]) { ->ft3 : Symbol(ft3, Decl(variadicTuples2.ts, 67, 27)) ->T : Symbol(T, Decl(variadicTuples2.ts, 69, 13)) ->x : Symbol(x, Decl(variadicTuples2.ts, 69, 34)) ->T : Symbol(T, Decl(variadicTuples2.ts, 69, 13)) ->y : Symbol(y, Decl(variadicTuples2.ts, 69, 52)) ->z : Symbol(z, Decl(variadicTuples2.ts, 69, 73)) +>ft3 : Symbol(ft3, Decl(variadicTuples2.ts, 72, 27)) +>T : Symbol(T, Decl(variadicTuples2.ts, 74, 13)) +>x : Symbol(x, Decl(variadicTuples2.ts, 74, 34)) +>T : Symbol(T, Decl(variadicTuples2.ts, 74, 13)) +>y : Symbol(y, Decl(variadicTuples2.ts, 74, 52)) +>z : Symbol(z, Decl(variadicTuples2.ts, 74, 73)) x = y; // Error ->x : Symbol(x, Decl(variadicTuples2.ts, 69, 34)) ->y : Symbol(y, Decl(variadicTuples2.ts, 69, 52)) +>x : Symbol(x, Decl(variadicTuples2.ts, 74, 34)) +>y : Symbol(y, Decl(variadicTuples2.ts, 74, 52)) x = z; // Error ->x : Symbol(x, Decl(variadicTuples2.ts, 69, 34)) ->z : Symbol(z, Decl(variadicTuples2.ts, 69, 73)) +>x : Symbol(x, Decl(variadicTuples2.ts, 74, 34)) +>z : Symbol(z, Decl(variadicTuples2.ts, 74, 73)) y = x; // Error ->y : Symbol(y, Decl(variadicTuples2.ts, 69, 52)) ->x : Symbol(x, Decl(variadicTuples2.ts, 69, 34)) +>y : Symbol(y, Decl(variadicTuples2.ts, 74, 52)) +>x : Symbol(x, Decl(variadicTuples2.ts, 74, 34)) z = x; // Error ->z : Symbol(z, Decl(variadicTuples2.ts, 69, 73)) ->x : Symbol(x, Decl(variadicTuples2.ts, 69, 34)) +>z : Symbol(z, Decl(variadicTuples2.ts, 74, 73)) +>x : Symbol(x, Decl(variadicTuples2.ts, 74, 34)) } // repro #50216 declare let tt3: [number, string, ...any[]] ->tt3 : Symbol(tt3, Decl(variadicTuples2.ts, 77, 11)) +>tt3 : Symbol(tt3, Decl(variadicTuples2.ts, 82, 11)) let tt4: [number, ...number[]] = tt3 // Error ->tt4 : Symbol(tt4, Decl(variadicTuples2.ts, 78, 3)) ->tt3 : Symbol(tt3, Decl(variadicTuples2.ts, 77, 11)) +>tt4 : Symbol(tt4, Decl(variadicTuples2.ts, 83, 3)) +>tt3 : Symbol(tt3, Decl(variadicTuples2.ts, 82, 11)) // Inference function pipe(...args: [...T, (...values: T) => void]) { ->pipe : Symbol(pipe, Decl(variadicTuples2.ts, 78, 36)) ->T : Symbol(T, Decl(variadicTuples2.ts, 82, 14)) ->args : Symbol(args, Decl(variadicTuples2.ts, 82, 44)) ->T : Symbol(T, Decl(variadicTuples2.ts, 82, 14)) ->values : Symbol(values, Decl(variadicTuples2.ts, 82, 61)) ->T : Symbol(T, Decl(variadicTuples2.ts, 82, 14)) +>pipe : Symbol(pipe, Decl(variadicTuples2.ts, 83, 36)) +>T : Symbol(T, Decl(variadicTuples2.ts, 87, 14)) +>args : Symbol(args, Decl(variadicTuples2.ts, 87, 44)) +>T : Symbol(T, Decl(variadicTuples2.ts, 87, 14)) +>values : Symbol(values, Decl(variadicTuples2.ts, 87, 61)) +>T : Symbol(T, Decl(variadicTuples2.ts, 87, 14)) const callback = args[args.length - 1] as (...values: T) => void; ->callback : Symbol(callback, Decl(variadicTuples2.ts, 83, 9)) ->args : Symbol(args, Decl(variadicTuples2.ts, 82, 44)) +>callback : Symbol(callback, Decl(variadicTuples2.ts, 88, 9)) +>args : Symbol(args, Decl(variadicTuples2.ts, 87, 44)) >args.length : Symbol(length) ->args : Symbol(args, Decl(variadicTuples2.ts, 82, 44)) +>args : Symbol(args, Decl(variadicTuples2.ts, 87, 44)) >length : Symbol(length) ->values : Symbol(values, Decl(variadicTuples2.ts, 83, 47)) ->T : Symbol(T, Decl(variadicTuples2.ts, 82, 14)) +>values : Symbol(values, Decl(variadicTuples2.ts, 88, 47)) +>T : Symbol(T, Decl(variadicTuples2.ts, 87, 14)) const values = args.slice(0, -1) as unknown as T; ->values : Symbol(values, Decl(variadicTuples2.ts, 84, 9)) +>values : Symbol(values, Decl(variadicTuples2.ts, 89, 9)) >args.slice : Symbol(Array.slice, Decl(lib.es5.d.ts, --, --)) ->args : Symbol(args, Decl(variadicTuples2.ts, 82, 44)) +>args : Symbol(args, Decl(variadicTuples2.ts, 87, 44)) >slice : Symbol(Array.slice, Decl(lib.es5.d.ts, --, --)) ->T : Symbol(T, Decl(variadicTuples2.ts, 82, 14)) +>T : Symbol(T, Decl(variadicTuples2.ts, 87, 14)) callback(...values); ->callback : Symbol(callback, Decl(variadicTuples2.ts, 83, 9)) ->values : Symbol(values, Decl(variadicTuples2.ts, 84, 9)) +>callback : Symbol(callback, Decl(variadicTuples2.ts, 88, 9)) +>values : Symbol(values, Decl(variadicTuples2.ts, 89, 9)) } pipe("foo", 123, true, (a, b, c) => { ->pipe : Symbol(pipe, Decl(variadicTuples2.ts, 78, 36)) ->a : Symbol(a, Decl(variadicTuples2.ts, 88, 24)) ->b : Symbol(b, Decl(variadicTuples2.ts, 88, 26)) ->c : Symbol(c, Decl(variadicTuples2.ts, 88, 29)) +>pipe : Symbol(pipe, Decl(variadicTuples2.ts, 83, 36)) +>a : Symbol(a, Decl(variadicTuples2.ts, 93, 24)) +>b : Symbol(b, Decl(variadicTuples2.ts, 93, 26)) +>c : Symbol(c, Decl(variadicTuples2.ts, 93, 29)) a; // string ->a : Symbol(a, Decl(variadicTuples2.ts, 88, 24)) +>a : Symbol(a, Decl(variadicTuples2.ts, 93, 24)) b; // number ->b : Symbol(b, Decl(variadicTuples2.ts, 88, 26)) +>b : Symbol(b, Decl(variadicTuples2.ts, 93, 26)) c; // boolean ->c : Symbol(c, Decl(variadicTuples2.ts, 88, 29)) +>c : Symbol(c, Decl(variadicTuples2.ts, 93, 29)) }) pipe("foo", 123, true, (...x) => { ->pipe : Symbol(pipe, Decl(variadicTuples2.ts, 78, 36)) ->x : Symbol(x, Decl(variadicTuples2.ts, 94, 24)) +>pipe : Symbol(pipe, Decl(variadicTuples2.ts, 83, 36)) +>x : Symbol(x, Decl(variadicTuples2.ts, 99, 24)) x; // [string, number, boolean] ->x : Symbol(x, Decl(variadicTuples2.ts, 94, 24)) +>x : Symbol(x, Decl(variadicTuples2.ts, 99, 24)) }); declare const sa: string[]; ->sa : Symbol(sa, Decl(variadicTuples2.ts, 98, 13)) +>sa : Symbol(sa, Decl(variadicTuples2.ts, 103, 13)) pipe(...sa, (...x) => { ->pipe : Symbol(pipe, Decl(variadicTuples2.ts, 78, 36)) ->sa : Symbol(sa, Decl(variadicTuples2.ts, 98, 13)) ->x : Symbol(x, Decl(variadicTuples2.ts, 100, 13)) +>pipe : Symbol(pipe, Decl(variadicTuples2.ts, 83, 36)) +>sa : Symbol(sa, Decl(variadicTuples2.ts, 103, 13)) +>x : Symbol(x, Decl(variadicTuples2.ts, 105, 13)) x; // string[] ->x : Symbol(x, Decl(variadicTuples2.ts, 100, 13)) +>x : Symbol(x, Decl(variadicTuples2.ts, 105, 13)) }); pipe(1, ...sa, 2, (...x) => { ->pipe : Symbol(pipe, Decl(variadicTuples2.ts, 78, 36)) ->sa : Symbol(sa, Decl(variadicTuples2.ts, 98, 13)) ->x : Symbol(x, Decl(variadicTuples2.ts, 104, 19)) +>pipe : Symbol(pipe, Decl(variadicTuples2.ts, 83, 36)) +>sa : Symbol(sa, Decl(variadicTuples2.ts, 103, 13)) +>x : Symbol(x, Decl(variadicTuples2.ts, 109, 19)) x; // [number, ...string[], number] ->x : Symbol(x, Decl(variadicTuples2.ts, 104, 19)) +>x : Symbol(x, Decl(variadicTuples2.ts, 109, 19)) let qq = x[x.length - 1]; ->qq : Symbol(qq, Decl(variadicTuples2.ts, 106, 7)) ->x : Symbol(x, Decl(variadicTuples2.ts, 104, 19)) +>qq : Symbol(qq, Decl(variadicTuples2.ts, 111, 7)) +>x : Symbol(x, Decl(variadicTuples2.ts, 109, 19)) >x.length : Symbol(length) ->x : Symbol(x, Decl(variadicTuples2.ts, 104, 19)) +>x : Symbol(x, Decl(variadicTuples2.ts, 109, 19)) >length : Symbol(length) let ww = x[0] ->ww : Symbol(ww, Decl(variadicTuples2.ts, 107, 7)) ->x : Symbol(x, Decl(variadicTuples2.ts, 104, 19)) +>ww : Symbol(ww, Decl(variadicTuples2.ts, 112, 7)) +>x : Symbol(x, Decl(variadicTuples2.ts, 109, 19)) >0 : Symbol(0) }); pipe(1, 2, 3, 4); // Error ->pipe : Symbol(pipe, Decl(variadicTuples2.ts, 78, 36)) +>pipe : Symbol(pipe, Decl(variadicTuples2.ts, 83, 36)) pipe(...sa); // Error ->pipe : Symbol(pipe, Decl(variadicTuples2.ts, 78, 36)) ->sa : Symbol(sa, Decl(variadicTuples2.ts, 98, 13)) +>pipe : Symbol(pipe, Decl(variadicTuples2.ts, 83, 36)) +>sa : Symbol(sa, Decl(variadicTuples2.ts, 103, 13)) declare function fn1(t: [...unknown[], T, U]): [T, U]; ->fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 111, 12)) ->T : Symbol(T, Decl(variadicTuples2.ts, 113, 21)) ->U : Symbol(U, Decl(variadicTuples2.ts, 113, 23)) ->t : Symbol(t, Decl(variadicTuples2.ts, 113, 27)) ->T : Symbol(T, Decl(variadicTuples2.ts, 113, 21)) ->U : Symbol(U, Decl(variadicTuples2.ts, 113, 23)) ->T : Symbol(T, Decl(variadicTuples2.ts, 113, 21)) ->U : Symbol(U, Decl(variadicTuples2.ts, 113, 23)) +>fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 116, 12)) +>T : Symbol(T, Decl(variadicTuples2.ts, 118, 21)) +>U : Symbol(U, Decl(variadicTuples2.ts, 118, 23)) +>t : Symbol(t, Decl(variadicTuples2.ts, 118, 27)) +>T : Symbol(T, Decl(variadicTuples2.ts, 118, 21)) +>U : Symbol(U, Decl(variadicTuples2.ts, 118, 23)) +>T : Symbol(T, Decl(variadicTuples2.ts, 118, 21)) +>U : Symbol(U, Decl(variadicTuples2.ts, 118, 23)) fn1([]); // Error ->fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 111, 12)) +>fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 116, 12)) fn1([1]); // Error ->fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 111, 12)) +>fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 116, 12)) fn1([1, 'abc']); // [number, string] ->fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 111, 12)) +>fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 116, 12)) fn1([1, 'abc', true]); // [string, boolean] ->fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 111, 12)) +>fn1 : Symbol(fn1, Decl(variadicTuples2.ts, 116, 12)) declare function fn2(t: [T, ...unknown[], U]): [T, U]; ->fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 117, 22)) ->T : Symbol(T, Decl(variadicTuples2.ts, 119, 21)) ->U : Symbol(U, Decl(variadicTuples2.ts, 119, 23)) ->t : Symbol(t, Decl(variadicTuples2.ts, 119, 27)) ->T : Symbol(T, Decl(variadicTuples2.ts, 119, 21)) ->U : Symbol(U, Decl(variadicTuples2.ts, 119, 23)) ->T : Symbol(T, Decl(variadicTuples2.ts, 119, 21)) ->U : Symbol(U, Decl(variadicTuples2.ts, 119, 23)) +>fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 122, 22)) +>T : Symbol(T, Decl(variadicTuples2.ts, 124, 21)) +>U : Symbol(U, Decl(variadicTuples2.ts, 124, 23)) +>t : Symbol(t, Decl(variadicTuples2.ts, 124, 27)) +>T : Symbol(T, Decl(variadicTuples2.ts, 124, 21)) +>U : Symbol(U, Decl(variadicTuples2.ts, 124, 23)) +>T : Symbol(T, Decl(variadicTuples2.ts, 124, 21)) +>U : Symbol(U, Decl(variadicTuples2.ts, 124, 23)) fn2([]); // Error ->fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 117, 22)) +>fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 122, 22)) fn2([1]); // Error ->fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 117, 22)) +>fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 122, 22)) fn2([1, 'abc']); // [number, string] ->fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 117, 22)) +>fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 122, 22)) fn2([1, 'abc', true]); // [number, boolean] ->fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 117, 22)) +>fn2 : Symbol(fn2, Decl(variadicTuples2.ts, 122, 22)) // Repro from #39595 declare function foo(...stringsAndNumber: readonly [...S, number]): [...S, number]; ->foo : Symbol(foo, Decl(variadicTuples2.ts, 123, 22)) ->S : Symbol(S, Decl(variadicTuples2.ts, 127, 21)) ->stringsAndNumber : Symbol(stringsAndNumber, Decl(variadicTuples2.ts, 127, 63)) ->S : Symbol(S, Decl(variadicTuples2.ts, 127, 21)) ->S : Symbol(S, Decl(variadicTuples2.ts, 127, 21)) +>foo : Symbol(foo, Decl(variadicTuples2.ts, 128, 22)) +>S : Symbol(S, Decl(variadicTuples2.ts, 132, 21)) +>stringsAndNumber : Symbol(stringsAndNumber, Decl(variadicTuples2.ts, 132, 63)) +>S : Symbol(S, Decl(variadicTuples2.ts, 132, 21)) +>S : Symbol(S, Decl(variadicTuples2.ts, 132, 21)) const a1 = foo('blah1', 1); ->a1 : Symbol(a1, Decl(variadicTuples2.ts, 129, 5)) ->foo : Symbol(foo, Decl(variadicTuples2.ts, 123, 22)) +>a1 : Symbol(a1, Decl(variadicTuples2.ts, 134, 5)) +>foo : Symbol(foo, Decl(variadicTuples2.ts, 128, 22)) const b1 = foo('blah1', 'blah2', 1); ->b1 : Symbol(b1, Decl(variadicTuples2.ts, 130, 5)) ->foo : Symbol(foo, Decl(variadicTuples2.ts, 123, 22)) +>b1 : Symbol(b1, Decl(variadicTuples2.ts, 135, 5)) +>foo : Symbol(foo, Decl(variadicTuples2.ts, 128, 22)) const c1 = foo(1); // Error ->c1 : Symbol(c1, Decl(variadicTuples2.ts, 131, 5)) ->foo : Symbol(foo, Decl(variadicTuples2.ts, 123, 22)) +>c1 : Symbol(c1, Decl(variadicTuples2.ts, 136, 5)) +>foo : Symbol(foo, Decl(variadicTuples2.ts, 128, 22)) const d1 = foo(1, 2); // Error ->d1 : Symbol(d1, Decl(variadicTuples2.ts, 132, 5)) ->foo : Symbol(foo, Decl(variadicTuples2.ts, 123, 22)) +>d1 : Symbol(d1, Decl(variadicTuples2.ts, 137, 5)) +>foo : Symbol(foo, Decl(variadicTuples2.ts, 128, 22)) const e1 = foo('blah1', 'blah2', 1, 2, 3); // Error ->e1 : Symbol(e1, Decl(variadicTuples2.ts, 133, 5)) ->foo : Symbol(foo, Decl(variadicTuples2.ts, 123, 22)) +>e1 : Symbol(e1, Decl(variadicTuples2.ts, 138, 5)) +>foo : Symbol(foo, Decl(variadicTuples2.ts, 128, 22)) diff --git a/tests/baselines/reference/variadicTuples2.types b/tests/baselines/reference/variadicTuples2.types index d80650c231e24..fb0f64a9cdbd7 100644 --- a/tests/baselines/reference/variadicTuples2.types +++ b/tests/baselines/reference/variadicTuples2.types @@ -21,6 +21,18 @@ type V11 = [number, ...string[], boolean?]; // Error type V12 = [number, string?, boolean]; // Error >V12 : [number, (string | undefined)?, boolean] +type V15 = [...string[], ...number[]]; // Error +>V15 : [...string[], ...number[]] + +type V16 = [...string[], ...Array]; // Error +>V16 : (string | number)[] + +type V17 = [...Array, ...number[]]; // Error +>V17 : (string | number)[] + +type V18 = [...Array, ...Array]; // Error +>V18 : (string | number)[] + // Normalization type Tup3 = [...T, ...U, ...V]; diff --git a/tests/cases/conformance/types/tuple/variadicTuples2.ts b/tests/cases/conformance/types/tuple/variadicTuples2.ts index 8ad04d44904b1..f999229550e71 100644 --- a/tests/cases/conformance/types/tuple/variadicTuples2.ts +++ b/tests/cases/conformance/types/tuple/variadicTuples2.ts @@ -11,6 +11,11 @@ type V10 = [number, ...string[], ...boolean[]]; // Error type V11 = [number, ...string[], boolean?]; // Error type V12 = [number, string?, boolean]; // Error +type V15 = [...string[], ...number[]]; // Error +type V16 = [...string[], ...Array]; // Error +type V17 = [...Array, ...number[]]; // Error +type V18 = [...Array, ...Array]; // Error + // Normalization type Tup3 = [...T, ...U, ...V];