diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1bacbfbead2e4..2cab4319e2d2a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27667,7 +27667,23 @@ namespace ts { case SyntaxKind.ArrayLiteralExpression: { const arrayLiteral = parent as ArrayLiteralExpression; const type = getApparentTypeOfContextualType(arrayLiteral, contextFlags); - return getContextualTypeForElementExpression(type, indexOfNode(arrayLiteral.elements, node)); + if (!type) return undefined; + const nodeIndex = indexOfNode(arrayLiteral.elements, node); + let filteredType = type; + if (type.flags & TypeFlags.Union) { + // If there is a union of tuples, filter down to only valid variants of the union + // based on previous elements in the tuple + for(let i = 0; i < nodeIndex; i++) { + const observedType = getTypeOfExpression(arrayLiteral.elements[i]); + if (getObjectFlags(observedType) & ObjectFlags.ArrayLiteral) continue; + filteredType = filterType(filteredType, (t) => { + const variantType = getTypeOfPropertyOfContextualType(t, "" + i as __String); + if (!variantType) return false; + return areTypesComparable(variantType, observedType); + }); + } + } + return getContextualTypeForElementExpression(filteredType, nodeIndex); } case SyntaxKind.ConditionalExpression: return getContextualTypeForConditionalOperand(node, contextFlags); diff --git a/tests/cases/fourslash/completionsTuple.ts b/tests/cases/fourslash/completionsTuple1.ts similarity index 100% rename from tests/cases/fourslash/completionsTuple.ts rename to tests/cases/fourslash/completionsTuple1.ts diff --git a/tests/cases/fourslash/completionsTuple2.ts b/tests/cases/fourslash/completionsTuple2.ts new file mode 100644 index 0000000000000..0e35c81c05ddb --- /dev/null +++ b/tests/cases/fourslash/completionsTuple2.ts @@ -0,0 +1,5 @@ +/// + +////declare const x: ["a", "b"] = ["x", "/**/"] + +verify.completions({ marker: "", exact: ["b"] }); diff --git a/tests/cases/fourslash/completionsTuple3.ts b/tests/cases/fourslash/completionsTuple3.ts new file mode 100644 index 0000000000000..c584e435557bf --- /dev/null +++ b/tests/cases/fourslash/completionsTuple3.ts @@ -0,0 +1,5 @@ +/// + +////declare const x: ["a", ["b"], "x", ["y"]] = ["a", ["/**/"]] + +verify.completions({ marker: "", exact: ["b"] }); diff --git a/tests/cases/fourslash/completionsTupleUnion1.ts b/tests/cases/fourslash/completionsTupleUnion1.ts new file mode 100644 index 0000000000000..4f625f08cdad6 --- /dev/null +++ b/tests/cases/fourslash/completionsTupleUnion1.ts @@ -0,0 +1,6 @@ +/// + +////declare const a: "a"; +////declare const x: ['a', 'b'] | ['a', 'c'] | ['d', 'e'] = [a, "/**/"]; + +verify.completions({ marker: "", exact: ["b", "c"] }); diff --git a/tests/cases/fourslash/completionsTupleUnion2.ts b/tests/cases/fourslash/completionsTupleUnion2.ts new file mode 100644 index 0000000000000..4c6dd0eca3139 --- /dev/null +++ b/tests/cases/fourslash/completionsTupleUnion2.ts @@ -0,0 +1,6 @@ +/// + +////declare const a: "a"; +////declare const x: [{ t: "a" }, "b"] | [{ t: "b" }, "c"] = [{ t: a }, "/**/"] + +verify.completions({ marker: "", exact: ["b"] });