From db1c440e870b7ed81bb05b3d1b7e21bfa430c486 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Thu, 13 Feb 2020 16:09:20 -0500 Subject: [PATCH] Proper treatment of splicing tuples in array literals Fixes #32465. After this was done, I continued to extend the implementation to handle TupleLike types but it'ss broken since JS doesn't allow splicing TupleLike values into array literals so pulled that out, and instead keeping it for reference below. (It Includes tests, which are broken too.) modified src/compiler/checker.ts @@ -22268,6 +22268,21 @@ namespace ts { else hasNonEndingSpreadElement = true; } } + else if (spreadType && isTupleLikeType(spreadType)) { + let i = 0, tupleEltType: Type | undefined; + while (tupleEltType = getTypeOfPropertyOfType(spreadType, "" + i as __String)) { + elementTypes.push(tupleEltType); + i++; + } + const stringIndexInfo = getIndexInfoOfType(spreadType, IndexKind.String); + const numberIndexInfo = getIndexInfoOfType(spreadType, IndexKind.Number); + if (stringIndexInfo || numberIndexInfo) { + if (stringIndexInfo) elementTypes.push(stringIndexInfo.type); + if (numberIndexInfo) elementTypes.push(numberIndexInfo.type); + if (i === elementCount - 1) hasEndingSpreadElement = true; + else hasNonEndingSpreadElement = true; + } + } else { if (inDestructuringPattern && spreadType) { // Given the following situation: new file tests/cases/compiler/spliceTupleLikesWIntegers.ts @@ -0,0 +1,23 @@ +declare const sb: { [0]: string, [1]: boolean }; + +let k1: [number, string, boolean]; +k1 = [1, ...sb]; + +let k2: [number, string, boolean, number]; +k2 = [1, ...sb, 1]; + +// declare const sb_: [string, ...boolean[]]; + +// let k3: [number, string, ...boolean[]]; +// k3 = [1, ...sb_]; + +// declare const sbb_: [string, boolean, ...boolean[]]; + +// let k4: [number, string, ...boolean[]]; +// k4 = [1, ...sbb_]; + +// let k5: [number, string, boolean, ...boolean[]]; +// k5 = [1, ...sbb_]; + +// let k6: [number, string, boolean, boolean, ...boolean[]]; +// k6 = [1, ...sbb_]; new file tests/cases/compiler/spliceTupleLikesWStrings.ts @@ -0,0 +1,23 @@ +declare const sb: { 0: string, 1: boolean }; + +let k1: [number, string, boolean]; +k1 = [1, ...sb]; + +let k2: [number, string, boolean, number]; +k2 = [1, ...sb, 1]; + +declare const sb_: { 0: string, [s: string]: (boolean|string) }; + +let k3: [number, string, ...(boolean|string)[]]; +k3 = [1, ...sb_]; + +declare const sbb_: { 0: string, 1: boolean, [s: string]: (boolean|string) }; + +let k4: [number, string, boolean, ...(boolean|string)[]]; +k4 = [1, ...sbb_]; + +// let k5: [number, string, boolean, ...(boolean|string)[]]; +// k5 = [1, ...sbb_]; + +// let k6: [number, string, boolean, boolean, ...(boolean|string)[]]; +// k6 = [1, ...sbb_]; --- src/compiler/checker.ts | 79 +++++++++++-------- ...teralExpressionContextualTyping.errors.txt | 8 +- ...rayLiteralExpressionContextualTyping.types | 2 +- .../reference/arrayLiterals3.errors.txt | 5 +- .../baselines/reference/arrayLiterals3.types | 2 +- tests/baselines/reference/constAssertions.js | 2 +- .../baselines/reference/constAssertions.types | 6 +- .../declarationsAndAssignments.types | 16 ++-- .../reference/destructuringTuple.types | 2 +- tests/baselines/reference/for-of49.types | 2 +- ...FreshnessPropagationOnNarrowing.errors.txt | 8 +- .../reference/restElementMustBeLast.types | 6 +- ...stElementWithAssignmentPattern1.errors.txt | 15 ---- .../restElementWithAssignmentPattern1.types | 6 +- .../restElementWithAssignmentPattern3.types | 2 +- .../restElementWithAssignmentPattern5.types | 6 +- .../reference/spliceTuples.errors.txt | 30 +++++++ tests/baselines/reference/spliceTuples.js | 46 +++++++++++ .../baselines/reference/spliceTuples.symbols | 52 ++++++++++++ tests/baselines/reference/spliceTuples.types | 77 ++++++++++++++++++ tests/cases/compiler/spliceTuples.ts | 23 ++++++ 21 files changed, 307 insertions(+), 88 deletions(-) delete mode 100644 tests/baselines/reference/restElementWithAssignmentPattern1.errors.txt create mode 100644 tests/baselines/reference/spliceTuples.errors.txt create mode 100644 tests/baselines/reference/spliceTuples.js create mode 100644 tests/baselines/reference/spliceTuples.symbols create mode 100644 tests/baselines/reference/spliceTuples.types create mode 100644 tests/cases/compiler/spliceTuples.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a1a0b598231b7..4582e03522bca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17182,7 +17182,7 @@ namespace ts { /** * Check if a Type was written as a tuple type literal. - * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. + * Prefer using isTupleLikeType() unless the use of `elementTypes`/`getTypeArguments` is required. */ function isTupleType(type: Type): type is TupleTypeReference { return !!(getObjectFlags(type) & ObjectFlags.Reference && (type).target.objectFlags & ObjectFlags.Tuple); @@ -22251,58 +22251,69 @@ namespace ts { function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined, forceTuple: boolean | undefined): Type { const elements = node.elements; const elementCount = elements.length; - let hasNonEndingSpreadElement = false; const elementTypes: Type[] = []; - const inDestructuringPattern = isAssignmentTarget(node); + let hasEndingSpreadElement = false; + let hasNonEndingSpreadElement = false; const contextualType = getApparentTypeOfContextualType(node); + const inDestructuringPattern = isAssignmentTarget(node); const inConstContext = isConstContext(node); - for (let index = 0; index < elementCount; index++) { - const e = elements[index]; - if (inDestructuringPattern && e.kind === SyntaxKind.SpreadElement) { - // Given the following situation: - // var c: {}; - // [...c] = ["", 0]; - // - // c is represented in the tree as a spread element in an array literal. - // But c really functions as a rest element, and its purpose is to provide - // a contextual type for the right hand side of the assignment. Therefore, - // instead of calling checkExpression on "...c", which will give an error - // if c is not iterable/array-like, we need to act as if we are trying to - // get the contextual element type from it. So we do something similar to - // getContextualTypeForElementExpression, which will crucially not error - // if there is no index type / iterated type. - const restArrayType = checkExpression((e).expression, checkMode, forceTuple); - const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) || - getIteratedTypeOrElementType(IterationUse.Destructuring, restArrayType, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false); - if (restElementType) { - elementTypes.push(restElementType); + for (let i = 0; i < elementCount; i++) { + const e = elements[i]; + const spread = e.kind === SyntaxKind.SpreadElement && (e).expression; + const spreadType = spread && checkExpression(spread, checkMode, forceTuple); + if (spreadType && isTupleType(spreadType)) { + elementTypes.push(...getTypeArguments(spreadType)); + if (spreadType.target.hasRestElement) { + if (i === elementCount - 1) hasEndingSpreadElement = true; + else hasNonEndingSpreadElement = true; } } else { - const elementContextualType = getContextualTypeForElementExpression(contextualType, index); - const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple); - elementTypes.push(type); - } - if (index < elementCount - 1 && e.kind === SyntaxKind.SpreadElement) { - hasNonEndingSpreadElement = true; + if (inDestructuringPattern && spreadType) { + // Given the following situation: + // var c: {}; + // [...c] = ["", 0]; + // + // c is represented in the tree as a spread element in an array literal. + // But c really functions as a rest element, and its purpose is to provide + // a contextual type for the right hand side of the assignment. Therefore, + // instead of calling checkExpression on "...c", which will give an error + // if c is not iterable/array-like, we need to act as if we are trying to + // get the contextual element type from it. So we do something similar to + // getContextualTypeForElementExpression, which will crucially not error + // if there is no index type / iterated type. + const restElementType = getIndexTypeOfType(spreadType, IndexKind.Number) || + getIteratedTypeOrElementType(IterationUse.Destructuring, spreadType, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false); + if (restElementType) { + elementTypes.push(restElementType); + } + } + else { + const elementContextualType = getContextualTypeForElementExpression(contextualType, elementTypes.length); + const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple); + elementTypes.push(type); + } + if (spread) { // tuples are done above, so these are only arrays + if (i === elementCount - 1) hasEndingSpreadElement = true; + else hasNonEndingSpreadElement = true; + } } } if (!hasNonEndingSpreadElement) { - const hasRestElement = elementCount > 0 && elements[elementCount - 1].kind === SyntaxKind.SpreadElement; - const minLength = elementCount - (hasRestElement ? 1 : 0); + const minLength = elementTypes.length - (hasEndingSpreadElement ? 1 : 0); // If array literal is actually a destructuring pattern, mark it as an implied type. We do this such // that we get the same behavior for "var [x, y] = []" and "[x, y] = []". let tupleResult; if (inDestructuringPattern && minLength > 0) { - const type = cloneTypeReference(createTupleType(elementTypes, minLength, hasRestElement)); + const type = cloneTypeReference(createTupleType(elementTypes, minLength, hasEndingSpreadElement)); type.pattern = node; return type; } - else if (tupleResult = getArrayLiteralTupleTypeIfApplicable(elementTypes, contextualType, hasRestElement, elementCount, inConstContext)) { + else if (tupleResult = getArrayLiteralTupleTypeIfApplicable(elementTypes, contextualType, hasEndingSpreadElement, elementTypes.length, inConstContext)) { return createArrayLiteralType(tupleResult); } else if (forceTuple) { - return createArrayLiteralType(createTupleType(elementTypes, minLength, hasRestElement)); + return createArrayLiteralType(createTupleType(elementTypes, minLength, hasEndingSpreadElement)); } } return createArrayLiteralType(createArrayType(elementTypes.length ? diff --git a/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt b/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt index e2d047ac711c1..8c62ba2d6b783 100644 --- a/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt +++ b/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt @@ -7,9 +7,9 @@ tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionConte tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(8,5): error TS2322: Type '[number, number, number, string]' is not assignable to type '[number, number, number]'. Types of property 'length' are incompatible. Type '4' is not assignable to type '3'. -tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(14,5): error TS2322: Type '[number, number, number, ...number[]]' is not assignable to type '[number, number, number]'. +tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(14,5): error TS2322: Type '[number, number, number, number, number, number]' is not assignable to type '[number, number, number]'. Types of property 'length' are incompatible. - Type 'number' is not assignable to type '3'. + Type '6' is not assignable to type '3'. ==== tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts (4 errors) ==== @@ -40,7 +40,7 @@ tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionConte var spr1 = [1, 2, 3, ...tup]; var spr2:[number, number, number] = [1, 2, 3, ...tup]; // Error ~~~~ -!!! error TS2322: Type '[number, number, number, ...number[]]' is not assignable to type '[number, number, number]'. +!!! error TS2322: Type '[number, number, number, number, number, number]' is not assignable to type '[number, number, number]'. !!! error TS2322: Types of property 'length' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type '3'. +!!! error TS2322: Type '6' is not assignable to type '3'. \ No newline at end of file diff --git a/tests/baselines/reference/arrayLiteralExpressionContextualTyping.types b/tests/baselines/reference/arrayLiteralExpressionContextualTyping.types index 3c1a9b6ba722b..dc942ebb9d5e8 100644 --- a/tests/baselines/reference/arrayLiteralExpressionContextualTyping.types +++ b/tests/baselines/reference/arrayLiteralExpressionContextualTyping.types @@ -62,7 +62,7 @@ var spr1 = [1, 2, 3, ...tup]; var spr2:[number, number, number] = [1, 2, 3, ...tup]; // Error >spr2 : [number, number, number] ->[1, 2, 3, ...tup] : [number, number, number, ...number[]] +>[1, 2, 3, ...tup] : [number, number, number, number, number, number] >1 : 1 >2 : 2 >3 : 3 diff --git a/tests/baselines/reference/arrayLiterals3.errors.txt b/tests/baselines/reference/arrayLiterals3.errors.txt index 5f592b74f3ebc..7a7213dd30b3e 100644 --- a/tests/baselines/reference/arrayLiterals3.errors.txt +++ b/tests/baselines/reference/arrayLiterals3.errors.txt @@ -5,7 +5,6 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(11,51): erro tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(17,5): error TS2322: Type '[number, number, string, boolean]' is not assignable to type '[number, number]'. Types of property 'length' are incompatible. Type '4' is not assignable to type '2'. -tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(32,5): error TS2739: Type '(number[] | string[])[]' is missing the following properties from type 'tup': 0, 1 tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(33,5): error TS2739: Type 'number[]' is missing the following properties from type '[number, number, number]': 0, 1, 2 tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error TS2322: Type '(string | number)[]' is not assignable to type 'myArray'. The types returned by 'pop()' are incompatible between these types. @@ -13,7 +12,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error Type 'string' is not assignable to type 'Number'. -==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts (8 errors) ==== +==== tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts (7 errors) ==== // Each element expression in a non-empty array literal is processed as follows: // - If the array literal contains no spread elements, and if the array literal is contextually typed (section 4.19) // by a type T and T has a property with the numeric name N, where N is the index of the element expression in the array literal, @@ -58,8 +57,6 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error interface myArray extends Array { } interface myArray2 extends Array { } var c0: tup = [...temp2]; // Error - ~~ -!!! error TS2739: Type '(number[] | string[])[]' is missing the following properties from type 'tup': 0, 1 var c1: [number, number, number] = [...temp1]; // Error cannot assign number[] to [number, number, number] ~~ !!! error TS2739: Type 'number[]' is missing the following properties from type '[number, number, number]': 0, 1, 2 diff --git a/tests/baselines/reference/arrayLiterals3.types b/tests/baselines/reference/arrayLiterals3.types index 44845feae035a..ec2aab18322c8 100644 --- a/tests/baselines/reference/arrayLiterals3.types +++ b/tests/baselines/reference/arrayLiterals3.types @@ -71,7 +71,7 @@ interface myArray extends Array { } interface myArray2 extends Array { } var c0: tup = [...temp2]; // Error >c0 : tup ->[...temp2] : (number[] | string[])[] +>[...temp2] : [number[], string[]] >...temp2 : number[] | string[] >temp2 : [number[], string[]] diff --git a/tests/baselines/reference/constAssertions.js b/tests/baselines/reference/constAssertions.js index c994db7a2565e..1dc997a2c5819 100644 --- a/tests/baselines/reference/constAssertions.js +++ b/tests/baselines/reference/constAssertions.js @@ -143,7 +143,7 @@ declare let vc1: "abc"; declare let a1: readonly []; declare let a2: readonly [1, 2, 3]; declare let a3: readonly [10, "hello", true]; -declare let a4: readonly (1 | 2 | 3)[]; +declare let a4: readonly [1, 2, 3]; declare let a5: number[]; declare let a6: readonly number[]; declare let a7: number[]; diff --git a/tests/baselines/reference/constAssertions.types b/tests/baselines/reference/constAssertions.types index 8ee3797f3a26d..68b442e0c4456 100644 --- a/tests/baselines/reference/constAssertions.types +++ b/tests/baselines/reference/constAssertions.types @@ -125,9 +125,9 @@ let a3 = [10, 'hello', true] as const; >true : true let a4 = [...[1, 2, 3]] as const; ->a4 : readonly (1 | 2 | 3)[] ->[...[1, 2, 3]] as const : readonly (1 | 2 | 3)[] ->[...[1, 2, 3]] : readonly (1 | 2 | 3)[] +>a4 : readonly [1, 2, 3] +>[...[1, 2, 3]] as const : readonly [1, 2, 3] +>[...[1, 2, 3]] : readonly [1, 2, 3] >...[1, 2, 3] : 1 | 2 | 3 >[1, 2, 3] : readonly [1, 2, 3] >1 : 1 diff --git a/tests/baselines/reference/declarationsAndAssignments.types b/tests/baselines/reference/declarationsAndAssignments.types index 3d4da894fdd86..8faf550681e2a 100644 --- a/tests/baselines/reference/declarationsAndAssignments.types +++ b/tests/baselines/reference/declarationsAndAssignments.types @@ -727,14 +727,14 @@ function f20(v: [number, number, number]) { [...a3] = v; >[...a3] = v : [number, number, number] ->[...a3] : number[] +>[...a3] : [number, number, number] >...a3 : number >a3 : [number, number, number] >v : [number, number, number] [x, ...a2] = v; >[x, ...a2] = v : [number, number, number] ->[x, ...a2] : [number, ...number[]] +>[x, ...a2] : [number, number, number] >x : number >...a2 : number >a2 : [number, number] @@ -742,7 +742,7 @@ function f20(v: [number, number, number]) { [x, y, ...a1] = v; >[x, y, ...a1] = v : [number, number, number] ->[x, y, ...a1] : [number, number, ...number[]] +>[x, y, ...a1] : [number, number, number] >x : number >y : number >...a1 : number @@ -751,7 +751,7 @@ function f20(v: [number, number, number]) { [x, y, z, ...a0] = v; >[x, y, z, ...a0] = v : [number, number, number] ->[x, y, z, ...a0] : [number, number, number, ...never[]] +>[x, y, z, ...a0] : [number, number, number] >x : number >y : number >z : number @@ -809,14 +809,14 @@ function f21(v: [number, string, boolean]) { [...a0] = v; >[...a0] = v : [number, string, boolean] ->[...a0] : (string | number | boolean)[] +>[...a0] : [number, string, boolean] >...a0 : string | number | boolean >a0 : [number, string, boolean] >v : [number, string, boolean] [x, ...a1] = v; >[x, ...a1] = v : [number, string, boolean] ->[x, ...a1] : [number, ...(string | boolean)[]] +>[x, ...a1] : [number, string, boolean] >x : number >...a1 : string | boolean >a1 : [string, boolean] @@ -824,7 +824,7 @@ function f21(v: [number, string, boolean]) { [x, y, ...a2] = v; >[x, y, ...a2] = v : [number, string, boolean] ->[x, y, ...a2] : [number, string, ...boolean[]] +>[x, y, ...a2] : [number, string, boolean] >x : number >y : string >...a2 : boolean @@ -833,7 +833,7 @@ function f21(v: [number, string, boolean]) { [x, y, z, ...a3] = v; >[x, y, z, ...a3] = v : [number, string, boolean] ->[x, y, z, ...a3] : [number, string, boolean, ...never[]] +>[x, y, z, ...a3] : [number, string, boolean] >x : number >y : string >z : boolean diff --git a/tests/baselines/reference/destructuringTuple.types b/tests/baselines/reference/destructuringTuple.types index dc946bd3d3d66..0227d82572ddc 100644 --- a/tests/baselines/reference/destructuringTuple.types +++ b/tests/baselines/reference/destructuringTuple.types @@ -15,7 +15,7 @@ declare var receiver: typeof tuple; [...receiver] = tuple; >[...receiver] = tuple : [boolean, number, ...string[]] ->[...receiver] : (string | number | boolean)[] +>[...receiver] : [boolean, number, ...string[]] >...receiver : string | number | boolean >receiver : [boolean, number, ...string[]] >tuple : [boolean, number, ...string[]] diff --git a/tests/baselines/reference/for-of49.types b/tests/baselines/reference/for-of49.types index fe46157c2864e..3666ba5432bed 100644 --- a/tests/baselines/reference/for-of49.types +++ b/tests/baselines/reference/for-of49.types @@ -13,7 +13,7 @@ var map = new Map([["", true]]); >true : true for ([k, ...[v]] of map) { ->[k, ...[v]] : [string, ...boolean[]] +>[k, ...[v]] : [string, boolean] >k : string >...[v] : boolean >[v] : [boolean] diff --git a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.errors.txt b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.errors.txt index 63e68d79d89bc..a2b08fbed9ef9 100644 --- a/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.errors.txt +++ b/tests/baselines/reference/literalFreshnessPropagationOnNarrowing.errors.txt @@ -1,6 +1,5 @@ tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts(37,5): error TS2322: Type '"y"' is not assignable to type '"x"'. -tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts(60,5): error TS2322: Type 'string[]' is not assignable to type 'XY[]'. - Type 'string' is not assignable to type 'XY'. +tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts(60,12): error TS2322: Type 'string' is not assignable to type 'XY'. ==== tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts (2 errors) ==== @@ -66,7 +65,6 @@ tests/cases/compiler/literalFreshnessPropagationOnNarrowing.ts(60,5): error TS23 // Desired: OK // Error in all extant branches arr = [...['y']]; - ~~~ -!!! error TS2322: Type 'string[]' is not assignable to type 'XY[]'. -!!! error TS2322: Type 'string' is not assignable to type 'XY'. + ~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'XY'. } \ No newline at end of file diff --git a/tests/baselines/reference/restElementMustBeLast.types b/tests/baselines/reference/restElementMustBeLast.types index 68276c7ef3d29..50b7fa5b4f1ea 100644 --- a/tests/baselines/reference/restElementMustBeLast.types +++ b/tests/baselines/reference/restElementMustBeLast.types @@ -8,12 +8,12 @@ var [...a, x] = [1, 2, 3]; // Error, rest must be last element >3 : 3 [...a, x] = [1, 2, 3]; // Error, rest must be last element ->[...a, x] = [1, 2, 3] : number[] ->[...a, x] : number[] +>[...a, x] = [1, 2, 3] : [number, number, number] +>[...a, x] : [number, number, number, number] >...a : number >a : [number, number, number] >x : number ->[1, 2, 3] : number[] +>[1, 2, 3] : [number, number, number] >1 : 1 >2 : 2 >3 : 3 diff --git a/tests/baselines/reference/restElementWithAssignmentPattern1.errors.txt b/tests/baselines/reference/restElementWithAssignmentPattern1.errors.txt deleted file mode 100644 index 2e1046c9317f5..0000000000000 --- a/tests/baselines/reference/restElementWithAssignmentPattern1.errors.txt +++ /dev/null @@ -1,15 +0,0 @@ -tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern1.ts(2,6): error TS2322: Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern1.ts(2,9): error TS2322: Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. - - -==== tests/cases/conformance/es6/destructuring/restElementWithAssignmentPattern1.ts (2 errors) ==== - var a: string, b: number; - [...[a, b = 0]] = ["", 1]; - ~ -!!! error TS2322: Type 'string | number' is not assignable to type 'string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. - ~ -!!! error TS2322: Type 'string | number' is not assignable to type 'number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/restElementWithAssignmentPattern1.types b/tests/baselines/reference/restElementWithAssignmentPattern1.types index 3740fc66343d0..c78541b88d07f 100644 --- a/tests/baselines/reference/restElementWithAssignmentPattern1.types +++ b/tests/baselines/reference/restElementWithAssignmentPattern1.types @@ -4,15 +4,15 @@ var a: string, b: number; >b : number [...[a, b = 0]] = ["", 1]; ->[...[a, b = 0]] = ["", 1] : (string | number)[] ->[...[a, b = 0]] : (string | number)[] +>[...[a, b = 0]] = ["", 1] : [string, number] +>[...[a, b = 0]] : [string, number] >...[a, b = 0] : string | number >[a, b = 0] : [string, number] >a : string >b = 0 : 0 >b : number >0 : 0 ->["", 1] : (string | number)[] +>["", 1] : [string, number] >"" : "" >1 : 1 diff --git a/tests/baselines/reference/restElementWithAssignmentPattern3.types b/tests/baselines/reference/restElementWithAssignmentPattern3.types index c2e01bc441455..dc5a378b440a2 100644 --- a/tests/baselines/reference/restElementWithAssignmentPattern3.types +++ b/tests/baselines/reference/restElementWithAssignmentPattern3.types @@ -11,7 +11,7 @@ var tuple: [string, number] = ["", 1]; [...[a, b = 0]] = tuple; >[...[a, b = 0]] = tuple : [string, number] ->[...[a, b = 0]] : (string | number)[] +>[...[a, b = 0]] : [string, number] >...[a, b = 0] : string | number >[a, b = 0] : [string, number] >a : string diff --git a/tests/baselines/reference/restElementWithAssignmentPattern5.types b/tests/baselines/reference/restElementWithAssignmentPattern5.types index 298bc2e4363f6..ea3cc010dcc9c 100644 --- a/tests/baselines/reference/restElementWithAssignmentPattern5.types +++ b/tests/baselines/reference/restElementWithAssignmentPattern5.types @@ -4,13 +4,13 @@ var s: string, s2: string; >s2 : string [...[s, s2]] = ["", ""]; ->[...[s, s2]] = ["", ""] : string[] ->[...[s, s2]] : string[] +>[...[s, s2]] = ["", ""] : [string, string] +>[...[s, s2]] : [string, string] >...[s, s2] : string >[s, s2] : [string, string] >s : string >s2 : string ->["", ""] : string[] +>["", ""] : [string, string] >"" : "" >"" : "" diff --git a/tests/baselines/reference/spliceTuples.errors.txt b/tests/baselines/reference/spliceTuples.errors.txt new file mode 100644 index 0000000000000..879f0659b3f94 --- /dev/null +++ b/tests/baselines/reference/spliceTuples.errors.txt @@ -0,0 +1,30 @@ +tests/cases/compiler/spliceTuples.ts(23,1): error TS2741: Property '3' is missing in type '[number, string, boolean, ...boolean[]]' but required in type '[number, string, boolean, boolean, ...boolean[]]'. + + +==== tests/cases/compiler/spliceTuples.ts (1 errors) ==== + declare const sb: [string, boolean]; + + let k1: [number, string, boolean]; + k1 = [1, ...sb]; + + let k2: [number, string, boolean, number]; + k2 = [1, ...sb, 1]; + + declare const sb_: [string, ...boolean[]]; + + let k3: [number, string, ...boolean[]]; + k3 = [1, ...sb_]; + + declare const sbb_: [string, boolean, ...boolean[]]; + + let k4: [number, string, ...boolean[]]; + k4 = [1, ...sbb_]; + + let k5: [number, string, boolean, ...boolean[]]; + k5 = [1, ...sbb_]; + + let k6: [number, string, boolean, boolean, ...boolean[]]; + k6 = [1, ...sbb_]; + ~~ +!!! error TS2741: Property '3' is missing in type '[number, string, boolean, ...boolean[]]' but required in type '[number, string, boolean, boolean, ...boolean[]]'. + \ No newline at end of file diff --git a/tests/baselines/reference/spliceTuples.js b/tests/baselines/reference/spliceTuples.js new file mode 100644 index 0000000000000..93deb0f614db9 --- /dev/null +++ b/tests/baselines/reference/spliceTuples.js @@ -0,0 +1,46 @@ +//// [spliceTuples.ts] +declare const sb: [string, boolean]; + +let k1: [number, string, boolean]; +k1 = [1, ...sb]; + +let k2: [number, string, boolean, number]; +k2 = [1, ...sb, 1]; + +declare const sb_: [string, ...boolean[]]; + +let k3: [number, string, ...boolean[]]; +k3 = [1, ...sb_]; + +declare const sbb_: [string, boolean, ...boolean[]]; + +let k4: [number, string, ...boolean[]]; +k4 = [1, ...sbb_]; + +let k5: [number, string, boolean, ...boolean[]]; +k5 = [1, ...sbb_]; + +let k6: [number, string, boolean, boolean, ...boolean[]]; +k6 = [1, ...sbb_]; + + +//// [spliceTuples.js] +var __spreadArrays = (this && this.__spreadArrays) || function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; +}; +var k1; +k1 = __spreadArrays([1], sb); +var k2; +k2 = __spreadArrays([1], sb, [1]); +var k3; +k3 = __spreadArrays([1], sb_); +var k4; +k4 = __spreadArrays([1], sbb_); +var k5; +k5 = __spreadArrays([1], sbb_); +var k6; +k6 = __spreadArrays([1], sbb_); diff --git a/tests/baselines/reference/spliceTuples.symbols b/tests/baselines/reference/spliceTuples.symbols new file mode 100644 index 0000000000000..f2df37e7c2e15 --- /dev/null +++ b/tests/baselines/reference/spliceTuples.symbols @@ -0,0 +1,52 @@ +=== tests/cases/compiler/spliceTuples.ts === +declare const sb: [string, boolean]; +>sb : Symbol(sb, Decl(spliceTuples.ts, 0, 13)) + +let k1: [number, string, boolean]; +>k1 : Symbol(k1, Decl(spliceTuples.ts, 2, 3)) + +k1 = [1, ...sb]; +>k1 : Symbol(k1, Decl(spliceTuples.ts, 2, 3)) +>sb : Symbol(sb, Decl(spliceTuples.ts, 0, 13)) + +let k2: [number, string, boolean, number]; +>k2 : Symbol(k2, Decl(spliceTuples.ts, 5, 3)) + +k2 = [1, ...sb, 1]; +>k2 : Symbol(k2, Decl(spliceTuples.ts, 5, 3)) +>sb : Symbol(sb, Decl(spliceTuples.ts, 0, 13)) + +declare const sb_: [string, ...boolean[]]; +>sb_ : Symbol(sb_, Decl(spliceTuples.ts, 8, 13)) + +let k3: [number, string, ...boolean[]]; +>k3 : Symbol(k3, Decl(spliceTuples.ts, 10, 3)) + +k3 = [1, ...sb_]; +>k3 : Symbol(k3, Decl(spliceTuples.ts, 10, 3)) +>sb_ : Symbol(sb_, Decl(spliceTuples.ts, 8, 13)) + +declare const sbb_: [string, boolean, ...boolean[]]; +>sbb_ : Symbol(sbb_, Decl(spliceTuples.ts, 13, 13)) + +let k4: [number, string, ...boolean[]]; +>k4 : Symbol(k4, Decl(spliceTuples.ts, 15, 3)) + +k4 = [1, ...sbb_]; +>k4 : Symbol(k4, Decl(spliceTuples.ts, 15, 3)) +>sbb_ : Symbol(sbb_, Decl(spliceTuples.ts, 13, 13)) + +let k5: [number, string, boolean, ...boolean[]]; +>k5 : Symbol(k5, Decl(spliceTuples.ts, 18, 3)) + +k5 = [1, ...sbb_]; +>k5 : Symbol(k5, Decl(spliceTuples.ts, 18, 3)) +>sbb_ : Symbol(sbb_, Decl(spliceTuples.ts, 13, 13)) + +let k6: [number, string, boolean, boolean, ...boolean[]]; +>k6 : Symbol(k6, Decl(spliceTuples.ts, 21, 3)) + +k6 = [1, ...sbb_]; +>k6 : Symbol(k6, Decl(spliceTuples.ts, 21, 3)) +>sbb_ : Symbol(sbb_, Decl(spliceTuples.ts, 13, 13)) + diff --git a/tests/baselines/reference/spliceTuples.types b/tests/baselines/reference/spliceTuples.types new file mode 100644 index 0000000000000..fa9342f774f0d --- /dev/null +++ b/tests/baselines/reference/spliceTuples.types @@ -0,0 +1,77 @@ +=== tests/cases/compiler/spliceTuples.ts === +declare const sb: [string, boolean]; +>sb : [string, boolean] + +let k1: [number, string, boolean]; +>k1 : [number, string, boolean] + +k1 = [1, ...sb]; +>k1 = [1, ...sb] : [number, string, boolean] +>k1 : [number, string, boolean] +>[1, ...sb] : [number, string, boolean] +>1 : 1 +>...sb : string | boolean +>sb : [string, boolean] + +let k2: [number, string, boolean, number]; +>k2 : [number, string, boolean, number] + +k2 = [1, ...sb, 1]; +>k2 = [1, ...sb, 1] : [number, string, boolean, number] +>k2 : [number, string, boolean, number] +>[1, ...sb, 1] : [number, string, boolean, number] +>1 : 1 +>...sb : string | boolean +>sb : [string, boolean] +>1 : 1 + +declare const sb_: [string, ...boolean[]]; +>sb_ : [string, ...boolean[]] + +let k3: [number, string, ...boolean[]]; +>k3 : [number, string, ...boolean[]] + +k3 = [1, ...sb_]; +>k3 = [1, ...sb_] : [number, string, ...boolean[]] +>k3 : [number, string, ...boolean[]] +>[1, ...sb_] : [number, string, ...boolean[]] +>1 : 1 +>...sb_ : string | boolean +>sb_ : [string, ...boolean[]] + +declare const sbb_: [string, boolean, ...boolean[]]; +>sbb_ : [string, boolean, ...boolean[]] + +let k4: [number, string, ...boolean[]]; +>k4 : [number, string, ...boolean[]] + +k4 = [1, ...sbb_]; +>k4 = [1, ...sbb_] : [number, string, boolean, ...boolean[]] +>k4 : [number, string, ...boolean[]] +>[1, ...sbb_] : [number, string, boolean, ...boolean[]] +>1 : 1 +>...sbb_ : string | boolean +>sbb_ : [string, boolean, ...boolean[]] + +let k5: [number, string, boolean, ...boolean[]]; +>k5 : [number, string, boolean, ...boolean[]] + +k5 = [1, ...sbb_]; +>k5 = [1, ...sbb_] : [number, string, boolean, ...boolean[]] +>k5 : [number, string, boolean, ...boolean[]] +>[1, ...sbb_] : [number, string, boolean, ...boolean[]] +>1 : 1 +>...sbb_ : string | boolean +>sbb_ : [string, boolean, ...boolean[]] + +let k6: [number, string, boolean, boolean, ...boolean[]]; +>k6 : [number, string, boolean, boolean, ...boolean[]] + +k6 = [1, ...sbb_]; +>k6 = [1, ...sbb_] : [number, string, boolean, ...boolean[]] +>k6 : [number, string, boolean, boolean, ...boolean[]] +>[1, ...sbb_] : [number, string, boolean, ...boolean[]] +>1 : 1 +>...sbb_ : string | boolean +>sbb_ : [string, boolean, ...boolean[]] + diff --git a/tests/cases/compiler/spliceTuples.ts b/tests/cases/compiler/spliceTuples.ts new file mode 100644 index 0000000000000..22f1cb185832b --- /dev/null +++ b/tests/cases/compiler/spliceTuples.ts @@ -0,0 +1,23 @@ +declare const sb: [string, boolean]; + +let k1: [number, string, boolean]; +k1 = [1, ...sb]; + +let k2: [number, string, boolean, number]; +k2 = [1, ...sb, 1]; + +declare const sb_: [string, ...boolean[]]; + +let k3: [number, string, ...boolean[]]; +k3 = [1, ...sb_]; + +declare const sbb_: [string, boolean, ...boolean[]]; + +let k4: [number, string, ...boolean[]]; +k4 = [1, ...sbb_]; + +let k5: [number, string, boolean, ...boolean[]]; +k5 = [1, ...sbb_]; + +let k6: [number, string, boolean, boolean, ...boolean[]]; +k6 = [1, ...sbb_];