From 83a873d9c7e97d0ad68c883de10344f26d5fc266 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Aug 2020 13:19:42 -1000 Subject: [PATCH 1/7] Consistently error when rest element isn't last in tuple type --- src/compiler/checker.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1eb750c8939ba..dc87bb0f33b3c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31121,6 +31121,7 @@ namespace ts { function checkTupleType(node: TupleTypeNode) { const elementTypes = node.elements; let seenOptionalElement = false; + let seenRestElement = false; const hasNamedElement = some(elementTypes, isNamedTupleMember); for (let i = 0; i < elementTypes.length; i++) { const e = elementTypes[i]; @@ -31130,16 +31131,17 @@ namespace ts { } const flags = getTupleElementFlags(e); if (flags & ElementFlags.Variadic) { - if (!isArrayLikeType(getTypeFromTypeNode((e).type))) { + const type = getTypeFromTypeNode((e).type); + if (!isArrayLikeType(type)) { error(e, Diagnostics.A_rest_element_type_must_be_an_array_type); break; } + if (isArrayType(type) || isTupleType(type) && type.target.combinedFlags & ElementFlags.Rest) { + seenRestElement = true; + } } else if (flags & ElementFlags.Rest) { - if (i !== elementTypes.length - 1) { - grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type); - break; - } + seenRestElement = true; } else if (flags & ElementFlags.Optional) { seenOptionalElement = true; @@ -31148,6 +31150,10 @@ namespace ts { grammarErrorOnNode(e, Diagnostics.A_required_element_cannot_follow_an_optional_element); break; } + if (seenRestElement && i !== elementTypes.length - 1) { + grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type); + break; + } } forEach(node.elements, checkSourceElement); } From fa46b6087785f078ed47c06b16735ea1a0b55e8e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Aug 2020 13:19:51 -1000 Subject: [PATCH 2/7] Add regression test --- tests/cases/conformance/types/tuple/variadicTuples1.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/cases/conformance/types/tuple/variadicTuples1.ts b/tests/cases/conformance/types/tuple/variadicTuples1.ts index d2e54ba2c1284..eeafb51510263 100644 --- a/tests/cases/conformance/types/tuple/variadicTuples1.ts +++ b/tests/cases/conformance/types/tuple/variadicTuples1.ts @@ -389,3 +389,13 @@ function callApi(method: (...args: [...T, ob callApi(getUser); callApi(getOrgUser); + +// Repro from #40235 + +type Numbers = number[]; +type Unbounded = [...Numbers, boolean]; +const data: Unbounded = [false, false]; + +type U1 = [string, ...Numbers, boolean]; +type U2 = [...[string, ...Numbers], boolean]; +type U3 = [...[string, number], boolean]; From 355706dadc8d2eb30f283e927d52d13736f6dd65 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Aug 2020 13:20:38 -1000 Subject: [PATCH 3/7] Accept new baselines --- .../reference/variadicTuples1.errors.txt | 21 +++++++++++++++- tests/baselines/reference/variadicTuples1.js | 17 +++++++++++++ .../reference/variadicTuples1.symbols | 24 +++++++++++++++++++ .../baselines/reference/variadicTuples1.types | 23 ++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/variadicTuples1.errors.txt b/tests/baselines/reference/variadicTuples1.errors.txt index db789540b9cda..416565221bbff 100644 --- a/tests/baselines/reference/variadicTuples1.errors.txt +++ b/tests/baselines/reference/variadicTuples1.errors.txt @@ -41,9 +41,12 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(203,5): error TS2322: Typ Type '"2"' is not assignable to type 'number | "0" | "length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight" | "1"'. tests/cases/conformance/types/tuple/variadicTuples1.ts(346,14): error TS7019: Rest parameter 'x' implicitly has an 'any[]' type. tests/cases/conformance/types/tuple/variadicTuples1.ts(354,26): error TS2322: Type 'string' is not assignable to type 'number | undefined'. +tests/cases/conformance/types/tuple/variadicTuples1.ts(393,19): error TS1256: A rest element must be last in a tuple type. +tests/cases/conformance/types/tuple/variadicTuples1.ts(396,20): error TS1256: A rest element must be last in a tuple type. +tests/cases/conformance/types/tuple/variadicTuples1.ts(397,12): error TS1256: A rest element must be last in a tuple type. -==== tests/cases/conformance/types/tuple/variadicTuples1.ts (20 errors) ==== +==== tests/cases/conformance/types/tuple/variadicTuples1.ts (23 errors) ==== // Variadics in tuple types type TV0 = [string, ...T]; @@ -496,4 +499,20 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(354,26): error TS2322: Ty callApi(getUser); callApi(getOrgUser); + + // Repro from #40235 + + type Numbers = number[]; + type Unbounded = [...Numbers, boolean]; + ~~~~~~~~~~ +!!! error TS1256: A rest element must be last in a tuple type. + const data: Unbounded = [false, false]; + + type U1 = [string, ...Numbers, boolean]; + ~~~~~~~~~~ +!!! error TS1256: A rest element must be last in a tuple type. + type U2 = [...[string, ...Numbers], boolean]; + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1256: A rest element must be last in a tuple type. + type U3 = [...[string, number], boolean]; \ No newline at end of file diff --git a/tests/baselines/reference/variadicTuples1.js b/tests/baselines/reference/variadicTuples1.js index 8447634732776..ee7ebc5c6a769 100644 --- a/tests/baselines/reference/variadicTuples1.js +++ b/tests/baselines/reference/variadicTuples1.js @@ -387,6 +387,16 @@ function callApi(method: (...args: [...T, ob callApi(getUser); callApi(getOrgUser); + +// Repro from #40235 + +type Numbers = number[]; +type Unbounded = [...Numbers, boolean]; +const data: Unbounded = [false, false]; + +type U1 = [string, ...Numbers, boolean]; +type U2 = [...[string, ...Numbers], boolean]; +type U3 = [...[string, number], boolean]; //// [variadicTuples1.js] @@ -609,6 +619,7 @@ function callApi(method) { } callApi(getUser); callApi(getOrgUser); +var data = [false, false]; //// [variadicTuples1.d.ts] @@ -774,3 +785,9 @@ declare function getOrgUser(id: string, orgId: number, options?: { z?: boolean; }): void; declare function callApi(method: (...args: [...T, object]) => U): (...args_0: T) => U; +declare type Numbers = number[]; +declare type Unbounded = [...Numbers, boolean]; +declare const data: Unbounded; +declare type U1 = [string, ...Numbers, boolean]; +declare type U2 = [...[string, ...Numbers], boolean]; +declare type U3 = [...[string, number], boolean]; diff --git a/tests/baselines/reference/variadicTuples1.symbols b/tests/baselines/reference/variadicTuples1.symbols index 034eda43f5a9e..b8029f3fbc0dc 100644 --- a/tests/baselines/reference/variadicTuples1.symbols +++ b/tests/baselines/reference/variadicTuples1.symbols @@ -1327,3 +1327,27 @@ callApi(getOrgUser); >callApi : Symbol(callApi, Decl(variadicTuples1.ts, 380, 100)) >getOrgUser : Symbol(getOrgUser, Decl(variadicTuples1.ts, 378, 71)) +// Repro from #40235 + +type Numbers = number[]; +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +type Unbounded = [...Numbers, boolean]; +>Unbounded : Symbol(Unbounded, Decl(variadicTuples1.ts, 391, 24)) +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +const data: Unbounded = [false, false]; +>data : Symbol(data, Decl(variadicTuples1.ts, 393, 5)) +>Unbounded : Symbol(Unbounded, Decl(variadicTuples1.ts, 391, 24)) + +type U1 = [string, ...Numbers, boolean]; +>U1 : Symbol(U1, Decl(variadicTuples1.ts, 393, 39)) +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +type U2 = [...[string, ...Numbers], boolean]; +>U2 : Symbol(U2, Decl(variadicTuples1.ts, 395, 40)) +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +type U3 = [...[string, number], boolean]; +>U3 : Symbol(U3, Decl(variadicTuples1.ts, 396, 45)) + diff --git a/tests/baselines/reference/variadicTuples1.types b/tests/baselines/reference/variadicTuples1.types index f4aacc3a2a29f..094932f783583 100644 --- a/tests/baselines/reference/variadicTuples1.types +++ b/tests/baselines/reference/variadicTuples1.types @@ -1383,3 +1383,26 @@ callApi(getOrgUser); >callApi : (method: (...args_0: T, args_1: object) => U) => (...args_0: T) => U >getOrgUser : (id: string, orgId: number, options?: { y?: number | undefined; z?: boolean | undefined; } | undefined) => void +// Repro from #40235 + +type Numbers = number[]; +>Numbers : Numbers + +type Unbounded = [...Numbers, boolean]; +>Unbounded : (number | boolean)[] + +const data: Unbounded = [false, false]; +>data : (number | boolean)[] +>[false, false] : false[] +>false : false +>false : false + +type U1 = [string, ...Numbers, boolean]; +>U1 : [string, ...(number | boolean)[]] + +type U2 = [...[string, ...Numbers], boolean]; +>U2 : [string, ...(number | boolean)[]] + +type U3 = [...[string, number], boolean]; +>U3 : [string, number, boolean] + From 80e6df6230ffc4f2416e23759c0749aa1cebf5d1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Aug 2020 13:54:24 -1000 Subject: [PATCH 4/7] Stricter circular recursion check in type inference --- src/compiler/checker.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dc87bb0f33b3c..73ef1975a9927 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19600,16 +19600,16 @@ namespace ts { // We stop inferring and report a circularity if we encounter duplicate recursion identities on both // the source side and the target side. const saveExpandingFlags = expandingFlags; - const sourceIdentity = getRecursionIdentity(source); - const targetIdentity = getRecursionIdentity(target); - if (sourceIdentity && contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source; - if (targetIdentity && contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target; + const sourceIdentity = getRecursionIdentity(source) || source; + const targetIdentity = getRecursionIdentity(target) || target; + if (contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source; + if (contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target; if (expandingFlags !== ExpandingFlags.Both) { - if (sourceIdentity) (sourceStack || (sourceStack = [])).push(sourceIdentity); - if (targetIdentity) (targetStack || (targetStack = [])).push(targetIdentity); + (sourceStack || (sourceStack = [])).push(sourceIdentity); + (targetStack || (targetStack = [])).push(targetIdentity); action(source, target); - if (targetIdentity) targetStack.pop(); - if (sourceIdentity) sourceStack.pop(); + targetStack.pop(); + sourceStack.pop(); } else { inferencePriority = InferencePriority.Circularity; From 0ca4e482b61b334b0ac8d1d66407b90b2c26dbc0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Aug 2020 20:34:05 -1000 Subject: [PATCH 5/7] Revert "Stricter circular recursion check in type inference" This reverts commit 80e6df6230ffc4f2416e23759c0749aa1cebf5d1. --- src/compiler/checker.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 73ef1975a9927..dc87bb0f33b3c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19600,16 +19600,16 @@ namespace ts { // We stop inferring and report a circularity if we encounter duplicate recursion identities on both // the source side and the target side. const saveExpandingFlags = expandingFlags; - const sourceIdentity = getRecursionIdentity(source) || source; - const targetIdentity = getRecursionIdentity(target) || target; - if (contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source; - if (contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target; + const sourceIdentity = getRecursionIdentity(source); + const targetIdentity = getRecursionIdentity(target); + if (sourceIdentity && contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source; + if (targetIdentity && contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target; if (expandingFlags !== ExpandingFlags.Both) { - (sourceStack || (sourceStack = [])).push(sourceIdentity); - (targetStack || (targetStack = [])).push(targetIdentity); + if (sourceIdentity) (sourceStack || (sourceStack = [])).push(sourceIdentity); + if (targetIdentity) (targetStack || (targetStack = [])).push(targetIdentity); action(source, target); - targetStack.pop(); - sourceStack.pop(); + if (targetIdentity) targetStack.pop(); + if (sourceIdentity) sourceStack.pop(); } else { inferencePriority = InferencePriority.Circularity; From 1ba3cc384c25ed6fa1ddaa50fc49e7cb141c2b02 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Aug 2020 20:35:36 -1000 Subject: [PATCH 6/7] Revert "Accept new baselines" This reverts commit 355706dadc8d2eb30f283e927d52d13736f6dd65. --- .../reference/variadicTuples1.errors.txt | 21 +--------------- tests/baselines/reference/variadicTuples1.js | 17 ------------- .../reference/variadicTuples1.symbols | 24 ------------------- .../baselines/reference/variadicTuples1.types | 23 ------------------ 4 files changed, 1 insertion(+), 84 deletions(-) diff --git a/tests/baselines/reference/variadicTuples1.errors.txt b/tests/baselines/reference/variadicTuples1.errors.txt index 416565221bbff..db789540b9cda 100644 --- a/tests/baselines/reference/variadicTuples1.errors.txt +++ b/tests/baselines/reference/variadicTuples1.errors.txt @@ -41,12 +41,9 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(203,5): error TS2322: Typ Type '"2"' is not assignable to type 'number | "0" | "length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight" | "1"'. tests/cases/conformance/types/tuple/variadicTuples1.ts(346,14): error TS7019: Rest parameter 'x' implicitly has an 'any[]' type. tests/cases/conformance/types/tuple/variadicTuples1.ts(354,26): error TS2322: Type 'string' is not assignable to type 'number | undefined'. -tests/cases/conformance/types/tuple/variadicTuples1.ts(393,19): error TS1256: A rest element must be last in a tuple type. -tests/cases/conformance/types/tuple/variadicTuples1.ts(396,20): error TS1256: A rest element must be last in a tuple type. -tests/cases/conformance/types/tuple/variadicTuples1.ts(397,12): error TS1256: A rest element must be last in a tuple type. -==== tests/cases/conformance/types/tuple/variadicTuples1.ts (23 errors) ==== +==== tests/cases/conformance/types/tuple/variadicTuples1.ts (20 errors) ==== // Variadics in tuple types type TV0 = [string, ...T]; @@ -499,20 +496,4 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(397,12): error TS1256: A callApi(getUser); callApi(getOrgUser); - - // Repro from #40235 - - type Numbers = number[]; - type Unbounded = [...Numbers, boolean]; - ~~~~~~~~~~ -!!! error TS1256: A rest element must be last in a tuple type. - const data: Unbounded = [false, false]; - - type U1 = [string, ...Numbers, boolean]; - ~~~~~~~~~~ -!!! error TS1256: A rest element must be last in a tuple type. - type U2 = [...[string, ...Numbers], boolean]; - ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1256: A rest element must be last in a tuple type. - type U3 = [...[string, number], boolean]; \ No newline at end of file diff --git a/tests/baselines/reference/variadicTuples1.js b/tests/baselines/reference/variadicTuples1.js index ee7ebc5c6a769..8447634732776 100644 --- a/tests/baselines/reference/variadicTuples1.js +++ b/tests/baselines/reference/variadicTuples1.js @@ -387,16 +387,6 @@ function callApi(method: (...args: [...T, ob callApi(getUser); callApi(getOrgUser); - -// Repro from #40235 - -type Numbers = number[]; -type Unbounded = [...Numbers, boolean]; -const data: Unbounded = [false, false]; - -type U1 = [string, ...Numbers, boolean]; -type U2 = [...[string, ...Numbers], boolean]; -type U3 = [...[string, number], boolean]; //// [variadicTuples1.js] @@ -619,7 +609,6 @@ function callApi(method) { } callApi(getUser); callApi(getOrgUser); -var data = [false, false]; //// [variadicTuples1.d.ts] @@ -785,9 +774,3 @@ declare function getOrgUser(id: string, orgId: number, options?: { z?: boolean; }): void; declare function callApi(method: (...args: [...T, object]) => U): (...args_0: T) => U; -declare type Numbers = number[]; -declare type Unbounded = [...Numbers, boolean]; -declare const data: Unbounded; -declare type U1 = [string, ...Numbers, boolean]; -declare type U2 = [...[string, ...Numbers], boolean]; -declare type U3 = [...[string, number], boolean]; diff --git a/tests/baselines/reference/variadicTuples1.symbols b/tests/baselines/reference/variadicTuples1.symbols index b8029f3fbc0dc..034eda43f5a9e 100644 --- a/tests/baselines/reference/variadicTuples1.symbols +++ b/tests/baselines/reference/variadicTuples1.symbols @@ -1327,27 +1327,3 @@ callApi(getOrgUser); >callApi : Symbol(callApi, Decl(variadicTuples1.ts, 380, 100)) >getOrgUser : Symbol(getOrgUser, Decl(variadicTuples1.ts, 378, 71)) -// Repro from #40235 - -type Numbers = number[]; ->Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) - -type Unbounded = [...Numbers, boolean]; ->Unbounded : Symbol(Unbounded, Decl(variadicTuples1.ts, 391, 24)) ->Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) - -const data: Unbounded = [false, false]; ->data : Symbol(data, Decl(variadicTuples1.ts, 393, 5)) ->Unbounded : Symbol(Unbounded, Decl(variadicTuples1.ts, 391, 24)) - -type U1 = [string, ...Numbers, boolean]; ->U1 : Symbol(U1, Decl(variadicTuples1.ts, 393, 39)) ->Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) - -type U2 = [...[string, ...Numbers], boolean]; ->U2 : Symbol(U2, Decl(variadicTuples1.ts, 395, 40)) ->Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) - -type U3 = [...[string, number], boolean]; ->U3 : Symbol(U3, Decl(variadicTuples1.ts, 396, 45)) - diff --git a/tests/baselines/reference/variadicTuples1.types b/tests/baselines/reference/variadicTuples1.types index 094932f783583..f4aacc3a2a29f 100644 --- a/tests/baselines/reference/variadicTuples1.types +++ b/tests/baselines/reference/variadicTuples1.types @@ -1383,26 +1383,3 @@ callApi(getOrgUser); >callApi : (method: (...args_0: T, args_1: object) => U) => (...args_0: T) => U >getOrgUser : (id: string, orgId: number, options?: { y?: number | undefined; z?: boolean | undefined; } | undefined) => void -// Repro from #40235 - -type Numbers = number[]; ->Numbers : Numbers - -type Unbounded = [...Numbers, boolean]; ->Unbounded : (number | boolean)[] - -const data: Unbounded = [false, false]; ->data : (number | boolean)[] ->[false, false] : false[] ->false : false ->false : false - -type U1 = [string, ...Numbers, boolean]; ->U1 : [string, ...(number | boolean)[]] - -type U2 = [...[string, ...Numbers], boolean]; ->U2 : [string, ...(number | boolean)[]] - -type U3 = [...[string, number], boolean]; ->U3 : [string, number, boolean] - From 13e80d812b3cec5d473239422264935582fbcde7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 25 Aug 2020 20:42:20 -1000 Subject: [PATCH 7/7] Accept new baselines --- .../reference/variadicTuples1.errors.txt | 21 +++++++++++++++- tests/baselines/reference/variadicTuples1.js | 17 +++++++++++++ .../reference/variadicTuples1.symbols | 24 +++++++++++++++++++ .../baselines/reference/variadicTuples1.types | 23 ++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/variadicTuples1.errors.txt b/tests/baselines/reference/variadicTuples1.errors.txt index db789540b9cda..416565221bbff 100644 --- a/tests/baselines/reference/variadicTuples1.errors.txt +++ b/tests/baselines/reference/variadicTuples1.errors.txt @@ -41,9 +41,12 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(203,5): error TS2322: Typ Type '"2"' is not assignable to type 'number | "0" | "length" | "toString" | "toLocaleString" | "pop" | "push" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight" | "1"'. tests/cases/conformance/types/tuple/variadicTuples1.ts(346,14): error TS7019: Rest parameter 'x' implicitly has an 'any[]' type. tests/cases/conformance/types/tuple/variadicTuples1.ts(354,26): error TS2322: Type 'string' is not assignable to type 'number | undefined'. +tests/cases/conformance/types/tuple/variadicTuples1.ts(393,19): error TS1256: A rest element must be last in a tuple type. +tests/cases/conformance/types/tuple/variadicTuples1.ts(396,20): error TS1256: A rest element must be last in a tuple type. +tests/cases/conformance/types/tuple/variadicTuples1.ts(397,12): error TS1256: A rest element must be last in a tuple type. -==== tests/cases/conformance/types/tuple/variadicTuples1.ts (20 errors) ==== +==== tests/cases/conformance/types/tuple/variadicTuples1.ts (23 errors) ==== // Variadics in tuple types type TV0 = [string, ...T]; @@ -496,4 +499,20 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(354,26): error TS2322: Ty callApi(getUser); callApi(getOrgUser); + + // Repro from #40235 + + type Numbers = number[]; + type Unbounded = [...Numbers, boolean]; + ~~~~~~~~~~ +!!! error TS1256: A rest element must be last in a tuple type. + const data: Unbounded = [false, false]; + + type U1 = [string, ...Numbers, boolean]; + ~~~~~~~~~~ +!!! error TS1256: A rest element must be last in a tuple type. + type U2 = [...[string, ...Numbers], boolean]; + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1256: A rest element must be last in a tuple type. + type U3 = [...[string, number], boolean]; \ No newline at end of file diff --git a/tests/baselines/reference/variadicTuples1.js b/tests/baselines/reference/variadicTuples1.js index 8447634732776..ee7ebc5c6a769 100644 --- a/tests/baselines/reference/variadicTuples1.js +++ b/tests/baselines/reference/variadicTuples1.js @@ -387,6 +387,16 @@ function callApi(method: (...args: [...T, ob callApi(getUser); callApi(getOrgUser); + +// Repro from #40235 + +type Numbers = number[]; +type Unbounded = [...Numbers, boolean]; +const data: Unbounded = [false, false]; + +type U1 = [string, ...Numbers, boolean]; +type U2 = [...[string, ...Numbers], boolean]; +type U3 = [...[string, number], boolean]; //// [variadicTuples1.js] @@ -609,6 +619,7 @@ function callApi(method) { } callApi(getUser); callApi(getOrgUser); +var data = [false, false]; //// [variadicTuples1.d.ts] @@ -774,3 +785,9 @@ declare function getOrgUser(id: string, orgId: number, options?: { z?: boolean; }): void; declare function callApi(method: (...args: [...T, object]) => U): (...args_0: T) => U; +declare type Numbers = number[]; +declare type Unbounded = [...Numbers, boolean]; +declare const data: Unbounded; +declare type U1 = [string, ...Numbers, boolean]; +declare type U2 = [...[string, ...Numbers], boolean]; +declare type U3 = [...[string, number], boolean]; diff --git a/tests/baselines/reference/variadicTuples1.symbols b/tests/baselines/reference/variadicTuples1.symbols index 034eda43f5a9e..b8029f3fbc0dc 100644 --- a/tests/baselines/reference/variadicTuples1.symbols +++ b/tests/baselines/reference/variadicTuples1.symbols @@ -1327,3 +1327,27 @@ callApi(getOrgUser); >callApi : Symbol(callApi, Decl(variadicTuples1.ts, 380, 100)) >getOrgUser : Symbol(getOrgUser, Decl(variadicTuples1.ts, 378, 71)) +// Repro from #40235 + +type Numbers = number[]; +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +type Unbounded = [...Numbers, boolean]; +>Unbounded : Symbol(Unbounded, Decl(variadicTuples1.ts, 391, 24)) +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +const data: Unbounded = [false, false]; +>data : Symbol(data, Decl(variadicTuples1.ts, 393, 5)) +>Unbounded : Symbol(Unbounded, Decl(variadicTuples1.ts, 391, 24)) + +type U1 = [string, ...Numbers, boolean]; +>U1 : Symbol(U1, Decl(variadicTuples1.ts, 393, 39)) +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +type U2 = [...[string, ...Numbers], boolean]; +>U2 : Symbol(U2, Decl(variadicTuples1.ts, 395, 40)) +>Numbers : Symbol(Numbers, Decl(variadicTuples1.ts, 387, 20)) + +type U3 = [...[string, number], boolean]; +>U3 : Symbol(U3, Decl(variadicTuples1.ts, 396, 45)) + diff --git a/tests/baselines/reference/variadicTuples1.types b/tests/baselines/reference/variadicTuples1.types index f4aacc3a2a29f..094932f783583 100644 --- a/tests/baselines/reference/variadicTuples1.types +++ b/tests/baselines/reference/variadicTuples1.types @@ -1383,3 +1383,26 @@ callApi(getOrgUser); >callApi : (method: (...args_0: T, args_1: object) => U) => (...args_0: T) => U >getOrgUser : (id: string, orgId: number, options?: { y?: number | undefined; z?: boolean | undefined; } | undefined) => void +// Repro from #40235 + +type Numbers = number[]; +>Numbers : Numbers + +type Unbounded = [...Numbers, boolean]; +>Unbounded : (number | boolean)[] + +const data: Unbounded = [false, false]; +>data : (number | boolean)[] +>[false, false] : false[] +>false : false +>false : false + +type U1 = [string, ...Numbers, boolean]; +>U1 : [string, ...(number | boolean)[]] + +type U2 = [...[string, ...Numbers], boolean]; +>U2 : [string, ...(number | boolean)[]] + +type U3 = [...[string, number], boolean]; +>U3 : [string, number, boolean] +