From f3d55db45af608dc6f10cb923a77238d19c7ee02 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 9 Dec 2022 10:59:40 -0500 Subject: [PATCH] Fixed tuple types indexed by a type parameter (#51037) * Fixed tuple types indexed by a type parameter * If only there was a tool to add that missing semicolon for me * Rename to baseConstraint Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/compiler/checker.ts | 5 +++-- .../reference/narrowingDestructuring.types | 4 ++-- .../spreadTupleAccessedByTypeParameter.js | 19 +++++++++++++++++ ...spreadTupleAccessedByTypeParameter.symbols | 21 +++++++++++++++++++ .../spreadTupleAccessedByTypeParameter.types | 21 +++++++++++++++++++ .../spreadTupleAccessedByTypeParameter.ts | 6 ++++++ 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/spreadTupleAccessedByTypeParameter.js create mode 100644 tests/baselines/reference/spreadTupleAccessedByTypeParameter.symbols create mode 100644 tests/baselines/reference/spreadTupleAccessedByTypeParameter.types create mode 100644 tests/cases/compiler/spreadTupleAccessedByTypeParameter.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3542a1e6c44..59f2d40799c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10090,8 +10090,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If the parent is a tuple type, the rest element has a tuple type of the // remaining tuple element types. Otherwise, the rest element has an array type with same // element type as the parent type. - type = everyType(parentType, isTupleType) ? - mapType(parentType, t => sliceTupleType(t as TupleTypeReference, index)) : + const baseConstraint = getBaseConstraintOrType(parentType); + type = everyType(baseConstraint, isTupleType) ? + mapType(baseConstraint, t => sliceTupleType(t as TupleTypeReference, index)) : createArrayType(elementType); } else if (isArrayLikeType(parentType)) { diff --git a/tests/baselines/reference/narrowingDestructuring.types b/tests/baselines/reference/narrowingDestructuring.types index 24ff38a297d..ee11c8c4448 100644 --- a/tests/baselines/reference/narrowingDestructuring.types +++ b/tests/baselines/reference/narrowingDestructuring.types @@ -132,7 +132,7 @@ function farr(x: const [head, ...tail] = x; >head : string | number ->tail : (string | number)[] +>tail : [string, string] | [number, number] >x : [number, string, string] | [string, number, number] if (x[0] === 'number') { @@ -144,7 +144,7 @@ function farr(x: const [head, ...tail] = x; >head : "number" ->tail : (string | number)[] +>tail : [string, string] | [number, number] >x : [number, string, string] | [string, number, number] } } diff --git a/tests/baselines/reference/spreadTupleAccessedByTypeParameter.js b/tests/baselines/reference/spreadTupleAccessedByTypeParameter.js new file mode 100644 index 00000000000..70778eeb180 --- /dev/null +++ b/tests/baselines/reference/spreadTupleAccessedByTypeParameter.js @@ -0,0 +1,19 @@ +//// [spreadTupleAccessedByTypeParameter.ts] +export function test(singletons: ["a"][], i: N) { + const singleton = singletons[i]; + const [, ...rest] = singleton; + + return rest; +} + + +//// [spreadTupleAccessedByTypeParameter.js] +"use strict"; +exports.__esModule = true; +exports.test = void 0; +function test(singletons, i) { + var singleton = singletons[i]; + var rest = singleton.slice(1); + return rest; +} +exports.test = test; diff --git a/tests/baselines/reference/spreadTupleAccessedByTypeParameter.symbols b/tests/baselines/reference/spreadTupleAccessedByTypeParameter.symbols new file mode 100644 index 00000000000..7316374c738 --- /dev/null +++ b/tests/baselines/reference/spreadTupleAccessedByTypeParameter.symbols @@ -0,0 +1,21 @@ +=== tests/cases/compiler/spreadTupleAccessedByTypeParameter.ts === +export function test(singletons: ["a"][], i: N) { +>test : Symbol(test, Decl(spreadTupleAccessedByTypeParameter.ts, 0, 0)) +>N : Symbol(N, Decl(spreadTupleAccessedByTypeParameter.ts, 0, 21)) +>singletons : Symbol(singletons, Decl(spreadTupleAccessedByTypeParameter.ts, 0, 39)) +>i : Symbol(i, Decl(spreadTupleAccessedByTypeParameter.ts, 0, 59)) +>N : Symbol(N, Decl(spreadTupleAccessedByTypeParameter.ts, 0, 21)) + + const singleton = singletons[i]; +>singleton : Symbol(singleton, Decl(spreadTupleAccessedByTypeParameter.ts, 1, 7)) +>singletons : Symbol(singletons, Decl(spreadTupleAccessedByTypeParameter.ts, 0, 39)) +>i : Symbol(i, Decl(spreadTupleAccessedByTypeParameter.ts, 0, 59)) + + const [, ...rest] = singleton; +>rest : Symbol(rest, Decl(spreadTupleAccessedByTypeParameter.ts, 2, 10)) +>singleton : Symbol(singleton, Decl(spreadTupleAccessedByTypeParameter.ts, 1, 7)) + + return rest; +>rest : Symbol(rest, Decl(spreadTupleAccessedByTypeParameter.ts, 2, 10)) +} + diff --git a/tests/baselines/reference/spreadTupleAccessedByTypeParameter.types b/tests/baselines/reference/spreadTupleAccessedByTypeParameter.types new file mode 100644 index 00000000000..1e73e2114ee --- /dev/null +++ b/tests/baselines/reference/spreadTupleAccessedByTypeParameter.types @@ -0,0 +1,21 @@ +=== tests/cases/compiler/spreadTupleAccessedByTypeParameter.ts === +export function test(singletons: ["a"][], i: N) { +>test : (singletons: ["a"][], i: N) => [] +>singletons : ["a"][] +>i : N + + const singleton = singletons[i]; +>singleton : ["a"][][N] +>singletons[i] : ["a"][][N] +>singletons : ["a"][] +>i : N + + const [, ...rest] = singleton; +> : undefined +>rest : [] +>singleton : ["a"][][N] + + return rest; +>rest : [] +} + diff --git a/tests/cases/compiler/spreadTupleAccessedByTypeParameter.ts b/tests/cases/compiler/spreadTupleAccessedByTypeParameter.ts new file mode 100644 index 00000000000..1d292613389 --- /dev/null +++ b/tests/cases/compiler/spreadTupleAccessedByTypeParameter.ts @@ -0,0 +1,6 @@ +export function test(singletons: ["a"][], i: N) { + const singleton = singletons[i]; + const [, ...rest] = singleton; + + return rest; +}