diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 397a424ee7b27..6eccec2a7f131 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32029,6 +32029,59 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); } + function discriminateContextualTypeByArrayElements(node: ArrayLiteralExpression, contextualType: UnionType) { + const key = `D${getNodeId(node)},${getTypeId(contextualType)}`; + const cachedType = getCachedType(key); + if (cachedType) return cachedType; + + const isIndexPropertyLike = (property: Symbol) => /^[-+]?\d+$/.test(property.escapedName as string); + const hasIndexPropertyOutOfRange = (type: Type, length: number) => + some(getPropertiesOfType(type), p => { + if (p.flags & SymbolFlags.Optional || !isIndexPropertyLike(p)) return false; + const index = +p.escapedName; + return index < 0 || index >= length; + }); + const hasIndexPropertyInRange = (type: Type, length: number) => + some(getPropertiesOfType(type), p => { + if (!isIndexPropertyLike(p)) return false; + const index = +p.escapedName; + return index >= 0 || index < length; + }); + + const elementsLength = node.elements.length; + const filteredType = filterType(contextualType, type => { + if (isTupleType(type)) { + return ( + elementsLength >= type.target.minLength && + (!!(type.target.combinedFlags & ElementFlags.Variable) || elementsLength <= type.target.fixedLength) + ); + } + return !hasIndexPropertyOutOfRange(type, elementsLength); + }); + + if (filteredType.flags & TypeFlags.Never) return setCachedType(key, filteredType); + if (!(filteredType.flags & TypeFlags.Union)) { + return setCachedType( + key, + isTupleType(filteredType) || hasIndexPropertyInRange(filteredType, elementsLength) ? filteredType : contextualType, + ); + } + + return setCachedType( + key, + discriminateTypeByDiscriminableItems( + filteredType as UnionType, + mapDefined(node.elements, (element, index) => { + const name = ("" + index) as __String; + return isPossiblyDiscriminantValue(element) && isDiscriminantProperty(filteredType, name) ? + [() => getContextFreeTypeOfExpression(element), name] as const : + undefined; + }), + isTypeAssignableTo, + ), + ); + } + // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node: Expression | MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { @@ -32046,9 +32099,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { t => getObjectFlags(t) & ObjectFlags.Mapped ? t : getApparentType(t), /*noReductions*/ true, ); - return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) : - apparentType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) : - apparentType; + if (apparentType.flags & TypeFlags.Union) { + if (isObjectLiteralExpression(node)) return discriminateContextualTypeByObjectMembers(node, apparentType as UnionType); + if (isJsxAttributes(node)) return discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType); + if (isArrayLiteralExpression(node)) return discriminateContextualTypeByArrayElements(node, apparentType as UnionType); + } + return apparentType; } } diff --git a/tests/baselines/reference/tupleTypeInference3.errors.txt b/tests/baselines/reference/tupleTypeInference3.errors.txt new file mode 100644 index 0000000000000..b653a338789f7 --- /dev/null +++ b/tests/baselines/reference/tupleTypeInference3.errors.txt @@ -0,0 +1,114 @@ +tupleTypeInference3.ts(16,7): error TS2322: Type '[1, (a: boolean) => void]' is not assignable to type 'T3'. + Type '[1, (a: boolean) => void]' is not assignable to type 'T1'. + Type at position 1 in source is not compatible with type at position 1 in target. + Type '(a: boolean) => void' is not assignable to type '(a: number) => void'. + Types of parameters 'a' and 'a' are incompatible. + Type 'number' is not assignable to type 'boolean'. +tupleTypeInference3.ts(30,22): error TS7006: Parameter 'a' implicitly has an 'any' type. +tupleTypeInference3.ts(35,22): error TS7006: Parameter 'a' implicitly has an 'any' type. +tupleTypeInference3.ts(45,24): error TS7006: Parameter 'a' implicitly has an 'any' type. +tupleTypeInference3.ts(64,7): error TS7006: Parameter 'a' implicitly has an 'any' type. +tupleTypeInference3.ts(70,8): error TS7006: Parameter 'arg' implicitly has an 'any' type. +tupleTypeInference3.ts(80,9): error TS7006: Parameter 'arg' implicitly has an 'any' type. + + +==== tupleTypeInference3.ts (7 errors) ==== + // Repro from #55632 + + type InferArg = + | [1, (a: number) => void] + | [2, (b: string) => void]; + const arg: InferArg = [1, (a) => { }]; + + // More tests + + type T1 = [1, (a: number) => void]; + type T2 = { 0: 1, 1: (a: boolean) => void, 2: number }; + type T3 = T1 | T2; + const v31: T3 = [1, (a) => { a === 0 }]; + const v32: T3 = [1, (a) => { a === true }, 0]; + const v33: T3 = [1, (a) => { a === true }, 0, 0]; + const v34: T3 = [1, (a: boolean) => { a === true }]; // Error + ~~~ +!!! error TS2322: Type '[1, (a: boolean) => void]' is not assignable to type 'T3'. +!!! error TS2322: Type '[1, (a: boolean) => void]' is not assignable to type 'T1'. +!!! error TS2322: Type at position 1 in source is not compatible with type at position 1 in target. +!!! error TS2322: Type '(a: boolean) => void' is not assignable to type '(a: number) => void'. +!!! error TS2322: Types of parameters 'a' and 'a' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'boolean'. + + type T4 = T3 | [2, (b: string) => void] + const v41: T4 = [1, (a) => { a === 0 }]; + const v42: T4 = [1, (a) => { a === true }, 0]; + const v43: T4 = [2, (a) => { a === "" }]; + + type T5 = T4 | {} + const v52: T5 = [1, (a) => { a === 0 }]; + const v53: T5 = [1, (a) => { a === true }, 0]; + const v54: T5 = [2, (a) => { a === "" }]; + + type T6 = T1 | { 0: 1, 1: (a: boolean) => void, 2?: number } + const v61: T6 = [1, (a) => { a === true }, 0]; + const v62: T6 = [1, (a) => { }]; // Error + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + + type T7 = [1, (a: number) => void, ...number[]]; + type T8 = T7 | [1, (a: boolean) => void] + const v81: T8 = [1, (a) => { a === 0 }, 0]; + const v82: T8 = [1, (a) => { }]; // Error + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + + type T9 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?]; + const v91: T9 = [1, (a) => { a === 0 }, 0, ""]; + const v92: T9 = [1, (a) => { a === "" }]; + const v93: T9 = [1, (a) => { a === "" }, 0]; + + type T10 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, string?]; + const v101: T10 = [1, (a) => { a === "" }]; + const v102: T10 = [1, (a) => { a === "" }, 0]; + const v103: T10 = [1, (a) => { }, 0, ""]; // Error + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + + type T11 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, boolean?]; + const v111: T11 = [1, (a) => { a === "" }]; + const v112: T11 = [1, (a) => { a === "" }, 0]; + const v113: T11 = [1, (a) => { a === 0 }, 0, ""]; + const v114: T11 = [1, (a) => { a === "" }, 0, true]; + + type T12 = + | { 1: (arg: File) => void } + | { 0?: number, 1: (arg: Date) => void } + | { 0: (arg: boolean) => void } + | { 0: boolean, 1: (arg: number) => void } + | [null, (arg: string) => void]; + declare function f(a: T12): void; + f([null, (a) => { a === "" }]); + f([true, (a) => { a === 0 }]); + f([(a) => { a === true }]); + f([0, (a) => { a as Date }]); + f([, (a) => { }]); // Error + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + + declare function f2(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2: any }): void; + f2([1, arg => { arg === 0 }] as const); + + declare function f3(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2?: any }): void; + f3([1, arg => { }] as const); // Error + ~~~ +!!! error TS7006: Parameter 'arg' implicitly has an 'any' type. + + declare function f4(_: [(arg: number) => void] | [(arg: string) => void, true]): void; + f4([arg => { arg === 0 }] as const); + + declare function f5(arg: { 0: null, 1: (arg: number) => void, foo?: string } | [1, (arg: boolean) => void]): void; + f5([null, (arg) => { arg === 0 }] as const); + f5([1, (arg) => { arg === true }] as const); + + declare function f6(arg: { 1: (arg: number) => void, [k: number]: (...args: never) => void } | [1, (arg: boolean) => void]): void; + f6([1, (arg) => { }] as const); // Error + ~~~ +!!! error TS7006: Parameter 'arg' implicitly has an 'any' type. \ No newline at end of file diff --git a/tests/baselines/reference/tupleTypeInference3.js b/tests/baselines/reference/tupleTypeInference3.js new file mode 100644 index 0000000000000..2882b07b7f2ad --- /dev/null +++ b/tests/baselines/reference/tupleTypeInference3.js @@ -0,0 +1,123 @@ +//// [tests/cases/compiler/tupleTypeInference3.ts] //// + +//// [tupleTypeInference3.ts] +// Repro from #55632 + +type InferArg = + | [1, (a: number) => void] + | [2, (b: string) => void]; +const arg: InferArg = [1, (a) => { }]; + +// More tests + +type T1 = [1, (a: number) => void]; +type T2 = { 0: 1, 1: (a: boolean) => void, 2: number }; +type T3 = T1 | T2; +const v31: T3 = [1, (a) => { a === 0 }]; +const v32: T3 = [1, (a) => { a === true }, 0]; +const v33: T3 = [1, (a) => { a === true }, 0, 0]; +const v34: T3 = [1, (a: boolean) => { a === true }]; // Error + +type T4 = T3 | [2, (b: string) => void] +const v41: T4 = [1, (a) => { a === 0 }]; +const v42: T4 = [1, (a) => { a === true }, 0]; +const v43: T4 = [2, (a) => { a === "" }]; + +type T5 = T4 | {} +const v52: T5 = [1, (a) => { a === 0 }]; +const v53: T5 = [1, (a) => { a === true }, 0]; +const v54: T5 = [2, (a) => { a === "" }]; + +type T6 = T1 | { 0: 1, 1: (a: boolean) => void, 2?: number } +const v61: T6 = [1, (a) => { a === true }, 0]; +const v62: T6 = [1, (a) => { }]; // Error + +type T7 = [1, (a: number) => void, ...number[]]; +type T8 = T7 | [1, (a: boolean) => void] +const v81: T8 = [1, (a) => { a === 0 }, 0]; +const v82: T8 = [1, (a) => { }]; // Error + +type T9 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?]; +const v91: T9 = [1, (a) => { a === 0 }, 0, ""]; +const v92: T9 = [1, (a) => { a === "" }]; +const v93: T9 = [1, (a) => { a === "" }, 0]; + +type T10 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, string?]; +const v101: T10 = [1, (a) => { a === "" }]; +const v102: T10 = [1, (a) => { a === "" }, 0]; +const v103: T10 = [1, (a) => { }, 0, ""]; // Error + +type T11 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, boolean?]; +const v111: T11 = [1, (a) => { a === "" }]; +const v112: T11 = [1, (a) => { a === "" }, 0]; +const v113: T11 = [1, (a) => { a === 0 }, 0, ""]; +const v114: T11 = [1, (a) => { a === "" }, 0, true]; + +type T12 = + | { 1: (arg: File) => void } + | { 0?: number, 1: (arg: Date) => void } + | { 0: (arg: boolean) => void } + | { 0: boolean, 1: (arg: number) => void } + | [null, (arg: string) => void]; +declare function f(a: T12): void; +f([null, (a) => { a === "" }]); +f([true, (a) => { a === 0 }]); +f([(a) => { a === true }]); +f([0, (a) => { a as Date }]); +f([, (a) => { }]); // Error + +declare function f2(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2: any }): void; +f2([1, arg => { arg === 0 }] as const); + +declare function f3(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2?: any }): void; +f3([1, arg => { }] as const); // Error + +declare function f4(_: [(arg: number) => void] | [(arg: string) => void, true]): void; +f4([arg => { arg === 0 }] as const); + +declare function f5(arg: { 0: null, 1: (arg: number) => void, foo?: string } | [1, (arg: boolean) => void]): void; +f5([null, (arg) => { arg === 0 }] as const); +f5([1, (arg) => { arg === true }] as const); + +declare function f6(arg: { 1: (arg: number) => void, [k: number]: (...args: never) => void } | [1, (arg: boolean) => void]): void; +f6([1, (arg) => { }] as const); // Error + +//// [tupleTypeInference3.js] +"use strict"; +// Repro from #55632 +var arg = [1, function (a) { }]; +var v31 = [1, function (a) { a === 0; }]; +var v32 = [1, function (a) { a === true; }, 0]; +var v33 = [1, function (a) { a === true; }, 0, 0]; +var v34 = [1, function (a) { a === true; }]; // Error +var v41 = [1, function (a) { a === 0; }]; +var v42 = [1, function (a) { a === true; }, 0]; +var v43 = [2, function (a) { a === ""; }]; +var v52 = [1, function (a) { a === 0; }]; +var v53 = [1, function (a) { a === true; }, 0]; +var v54 = [2, function (a) { a === ""; }]; +var v61 = [1, function (a) { a === true; }, 0]; +var v62 = [1, function (a) { }]; // Error +var v81 = [1, function (a) { a === 0; }, 0]; +var v82 = [1, function (a) { }]; // Error +var v91 = [1, function (a) { a === 0; }, 0, ""]; +var v92 = [1, function (a) { a === ""; }]; +var v93 = [1, function (a) { a === ""; }, 0]; +var v101 = [1, function (a) { a === ""; }]; +var v102 = [1, function (a) { a === ""; }, 0]; +var v103 = [1, function (a) { }, 0, ""]; // Error +var v111 = [1, function (a) { a === ""; }]; +var v112 = [1, function (a) { a === ""; }, 0]; +var v113 = [1, function (a) { a === 0; }, 0, ""]; +var v114 = [1, function (a) { a === ""; }, 0, true]; +f([null, function (a) { a === ""; }]); +f([true, function (a) { a === 0; }]); +f([function (a) { a === true; }]); +f([0, function (a) { a; }]); +f([, function (a) { }]); // Error +f2([1, function (arg) { arg === 0; }]); +f3([1, function (arg) { }]); // Error +f4([function (arg) { arg === 0; }]); +f5([null, function (arg) { arg === 0; }]); +f5([1, function (arg) { arg === true; }]); +f6([1, function (arg) { }]); // Error diff --git a/tests/baselines/reference/tupleTypeInference3.symbols b/tests/baselines/reference/tupleTypeInference3.symbols new file mode 100644 index 0000000000000..d32f7c1f99d5e --- /dev/null +++ b/tests/baselines/reference/tupleTypeInference3.symbols @@ -0,0 +1,355 @@ +//// [tests/cases/compiler/tupleTypeInference3.ts] //// + +=== tupleTypeInference3.ts === +// Repro from #55632 + +type InferArg = +>InferArg : Symbol(InferArg, Decl(tupleTypeInference3.ts, 0, 0)) + + | [1, (a: number) => void] +>a : Symbol(a, Decl(tupleTypeInference3.ts, 3, 9)) + + | [2, (b: string) => void]; +>b : Symbol(b, Decl(tupleTypeInference3.ts, 4, 9)) + +const arg: InferArg = [1, (a) => { }]; +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 5, 5)) +>InferArg : Symbol(InferArg, Decl(tupleTypeInference3.ts, 0, 0)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 5, 27)) + +// More tests + +type T1 = [1, (a: number) => void]; +>T1 : Symbol(T1, Decl(tupleTypeInference3.ts, 5, 38)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 9, 15)) + +type T2 = { 0: 1, 1: (a: boolean) => void, 2: number }; +>T2 : Symbol(T2, Decl(tupleTypeInference3.ts, 9, 35)) +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 10, 11)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 10, 17)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 10, 22)) +>2 : Symbol(2, Decl(tupleTypeInference3.ts, 10, 42)) + +type T3 = T1 | T2; +>T3 : Symbol(T3, Decl(tupleTypeInference3.ts, 10, 55)) +>T1 : Symbol(T1, Decl(tupleTypeInference3.ts, 5, 38)) +>T2 : Symbol(T2, Decl(tupleTypeInference3.ts, 9, 35)) + +const v31: T3 = [1, (a) => { a === 0 }]; +>v31 : Symbol(v31, Decl(tupleTypeInference3.ts, 12, 5)) +>T3 : Symbol(T3, Decl(tupleTypeInference3.ts, 10, 55)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 12, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 12, 21)) + +const v32: T3 = [1, (a) => { a === true }, 0]; +>v32 : Symbol(v32, Decl(tupleTypeInference3.ts, 13, 5)) +>T3 : Symbol(T3, Decl(tupleTypeInference3.ts, 10, 55)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 13, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 13, 21)) + +const v33: T3 = [1, (a) => { a === true }, 0, 0]; +>v33 : Symbol(v33, Decl(tupleTypeInference3.ts, 14, 5)) +>T3 : Symbol(T3, Decl(tupleTypeInference3.ts, 10, 55)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 14, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 14, 21)) + +const v34: T3 = [1, (a: boolean) => { a === true }]; // Error +>v34 : Symbol(v34, Decl(tupleTypeInference3.ts, 15, 5)) +>T3 : Symbol(T3, Decl(tupleTypeInference3.ts, 10, 55)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 15, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 15, 21)) + +type T4 = T3 | [2, (b: string) => void] +>T4 : Symbol(T4, Decl(tupleTypeInference3.ts, 15, 52)) +>T3 : Symbol(T3, Decl(tupleTypeInference3.ts, 10, 55)) +>b : Symbol(b, Decl(tupleTypeInference3.ts, 17, 20)) + +const v41: T4 = [1, (a) => { a === 0 }]; +>v41 : Symbol(v41, Decl(tupleTypeInference3.ts, 18, 5)) +>T4 : Symbol(T4, Decl(tupleTypeInference3.ts, 15, 52)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 18, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 18, 21)) + +const v42: T4 = [1, (a) => { a === true }, 0]; +>v42 : Symbol(v42, Decl(tupleTypeInference3.ts, 19, 5)) +>T4 : Symbol(T4, Decl(tupleTypeInference3.ts, 15, 52)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 19, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 19, 21)) + +const v43: T4 = [2, (a) => { a === "" }]; +>v43 : Symbol(v43, Decl(tupleTypeInference3.ts, 20, 5)) +>T4 : Symbol(T4, Decl(tupleTypeInference3.ts, 15, 52)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 20, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 20, 21)) + +type T5 = T4 | {} +>T5 : Symbol(T5, Decl(tupleTypeInference3.ts, 20, 41)) +>T4 : Symbol(T4, Decl(tupleTypeInference3.ts, 15, 52)) + +const v52: T5 = [1, (a) => { a === 0 }]; +>v52 : Symbol(v52, Decl(tupleTypeInference3.ts, 23, 5)) +>T5 : Symbol(T5, Decl(tupleTypeInference3.ts, 20, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 23, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 23, 21)) + +const v53: T5 = [1, (a) => { a === true }, 0]; +>v53 : Symbol(v53, Decl(tupleTypeInference3.ts, 24, 5)) +>T5 : Symbol(T5, Decl(tupleTypeInference3.ts, 20, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 24, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 24, 21)) + +const v54: T5 = [2, (a) => { a === "" }]; +>v54 : Symbol(v54, Decl(tupleTypeInference3.ts, 25, 5)) +>T5 : Symbol(T5, Decl(tupleTypeInference3.ts, 20, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 25, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 25, 21)) + +type T6 = T1 | { 0: 1, 1: (a: boolean) => void, 2?: number } +>T6 : Symbol(T6, Decl(tupleTypeInference3.ts, 25, 41)) +>T1 : Symbol(T1, Decl(tupleTypeInference3.ts, 5, 38)) +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 27, 16)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 27, 22)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 27, 27)) +>2 : Symbol(2, Decl(tupleTypeInference3.ts, 27, 47)) + +const v61: T6 = [1, (a) => { a === true }, 0]; +>v61 : Symbol(v61, Decl(tupleTypeInference3.ts, 28, 5)) +>T6 : Symbol(T6, Decl(tupleTypeInference3.ts, 25, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 28, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 28, 21)) + +const v62: T6 = [1, (a) => { }]; // Error +>v62 : Symbol(v62, Decl(tupleTypeInference3.ts, 29, 5)) +>T6 : Symbol(T6, Decl(tupleTypeInference3.ts, 25, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 29, 21)) + +type T7 = [1, (a: number) => void, ...number[]]; +>T7 : Symbol(T7, Decl(tupleTypeInference3.ts, 29, 32)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 31, 15)) + +type T8 = T7 | [1, (a: boolean) => void] +>T8 : Symbol(T8, Decl(tupleTypeInference3.ts, 31, 48)) +>T7 : Symbol(T7, Decl(tupleTypeInference3.ts, 29, 32)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 32, 20)) + +const v81: T8 = [1, (a) => { a === 0 }, 0]; +>v81 : Symbol(v81, Decl(tupleTypeInference3.ts, 33, 5)) +>T8 : Symbol(T8, Decl(tupleTypeInference3.ts, 31, 48)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 33, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 33, 21)) + +const v82: T8 = [1, (a) => { }]; // Error +>v82 : Symbol(v82, Decl(tupleTypeInference3.ts, 34, 5)) +>T8 : Symbol(T8, Decl(tupleTypeInference3.ts, 31, 48)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 34, 21)) + +type T9 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?]; +>T9 : Symbol(T9, Decl(tupleTypeInference3.ts, 34, 32)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 36, 15)) +>b : Symbol(b, Decl(tupleTypeInference3.ts, 36, 63)) + +const v91: T9 = [1, (a) => { a === 0 }, 0, ""]; +>v91 : Symbol(v91, Decl(tupleTypeInference3.ts, 37, 5)) +>T9 : Symbol(T9, Decl(tupleTypeInference3.ts, 34, 32)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 37, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 37, 21)) + +const v92: T9 = [1, (a) => { a === "" }]; +>v92 : Symbol(v92, Decl(tupleTypeInference3.ts, 38, 5)) +>T9 : Symbol(T9, Decl(tupleTypeInference3.ts, 34, 32)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 38, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 38, 21)) + +const v93: T9 = [1, (a) => { a === "" }, 0]; +>v93 : Symbol(v93, Decl(tupleTypeInference3.ts, 39, 5)) +>T9 : Symbol(T9, Decl(tupleTypeInference3.ts, 34, 32)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 39, 21)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 39, 21)) + +type T10 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, string?]; +>T10 : Symbol(T10, Decl(tupleTypeInference3.ts, 39, 44)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 41, 16)) +>b : Symbol(b, Decl(tupleTypeInference3.ts, 41, 64)) + +const v101: T10 = [1, (a) => { a === "" }]; +>v101 : Symbol(v101, Decl(tupleTypeInference3.ts, 42, 5)) +>T10 : Symbol(T10, Decl(tupleTypeInference3.ts, 39, 44)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 42, 23)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 42, 23)) + +const v102: T10 = [1, (a) => { a === "" }, 0]; +>v102 : Symbol(v102, Decl(tupleTypeInference3.ts, 43, 5)) +>T10 : Symbol(T10, Decl(tupleTypeInference3.ts, 39, 44)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 43, 23)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 43, 23)) + +const v103: T10 = [1, (a) => { }, 0, ""]; // Error +>v103 : Symbol(v103, Decl(tupleTypeInference3.ts, 44, 5)) +>T10 : Symbol(T10, Decl(tupleTypeInference3.ts, 39, 44)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 44, 23)) + +type T11 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, boolean?]; +>T11 : Symbol(T11, Decl(tupleTypeInference3.ts, 44, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 46, 16)) +>b : Symbol(b, Decl(tupleTypeInference3.ts, 46, 64)) + +const v111: T11 = [1, (a) => { a === "" }]; +>v111 : Symbol(v111, Decl(tupleTypeInference3.ts, 47, 5)) +>T11 : Symbol(T11, Decl(tupleTypeInference3.ts, 44, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 47, 23)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 47, 23)) + +const v112: T11 = [1, (a) => { a === "" }, 0]; +>v112 : Symbol(v112, Decl(tupleTypeInference3.ts, 48, 5)) +>T11 : Symbol(T11, Decl(tupleTypeInference3.ts, 44, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 48, 23)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 48, 23)) + +const v113: T11 = [1, (a) => { a === 0 }, 0, ""]; +>v113 : Symbol(v113, Decl(tupleTypeInference3.ts, 49, 5)) +>T11 : Symbol(T11, Decl(tupleTypeInference3.ts, 44, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 49, 23)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 49, 23)) + +const v114: T11 = [1, (a) => { a === "" }, 0, true]; +>v114 : Symbol(v114, Decl(tupleTypeInference3.ts, 50, 5)) +>T11 : Symbol(T11, Decl(tupleTypeInference3.ts, 44, 41)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 50, 23)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 50, 23)) + +type T12 = +>T12 : Symbol(T12, Decl(tupleTypeInference3.ts, 50, 52)) + + | { 1: (arg: File) => void } +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 53, 5)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 53, 10)) +>File : Symbol(File, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + | { 0?: number, 1: (arg: Date) => void } +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 54, 5)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 54, 17)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 54, 22)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + + | { 0: (arg: boolean) => void } +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 55, 5)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 55, 10)) + + | { 0: boolean, 1: (arg: number) => void } +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 56, 5)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 56, 17)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 56, 22)) + + | [null, (arg: string) => void]; +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 57, 12)) + +declare function f(a: T12): void; +>f : Symbol(f, Decl(tupleTypeInference3.ts, 57, 34)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 58, 19)) +>T12 : Symbol(T12, Decl(tupleTypeInference3.ts, 50, 52)) + +f([null, (a) => { a === "" }]); +>f : Symbol(f, Decl(tupleTypeInference3.ts, 57, 34)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 59, 10)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 59, 10)) + +f([true, (a) => { a === 0 }]); +>f : Symbol(f, Decl(tupleTypeInference3.ts, 57, 34)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 60, 10)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 60, 10)) + +f([(a) => { a === true }]); +>f : Symbol(f, Decl(tupleTypeInference3.ts, 57, 34)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 61, 4)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 61, 4)) + +f([0, (a) => { a as Date }]); +>f : Symbol(f, Decl(tupleTypeInference3.ts, 57, 34)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 62, 7)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 62, 7)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + +f([, (a) => { }]); // Error +>f : Symbol(f, Decl(tupleTypeInference3.ts, 57, 34)) +>a : Symbol(a, Decl(tupleTypeInference3.ts, 63, 6)) + +declare function f2(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2: any }): void; +>f2 : Symbol(f2, Decl(tupleTypeInference3.ts, 63, 18)) +>_ : Symbol(_, Decl(tupleTypeInference3.ts, 65, 20)) +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 65, 24)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 65, 35)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 65, 40)) +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 65, 66)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 65, 77)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 65, 82)) +>2 : Symbol(2, Decl(tupleTypeInference3.ts, 65, 104)) + +f2([1, arg => { arg === 0 }] as const); +>f2 : Symbol(f2, Decl(tupleTypeInference3.ts, 63, 18)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 66, 6)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 66, 6)) +>const : Symbol(const) + +declare function f3(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2?: any }): void; +>f3 : Symbol(f3, Decl(tupleTypeInference3.ts, 66, 39)) +>_ : Symbol(_, Decl(tupleTypeInference3.ts, 68, 20)) +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 68, 24)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 68, 35)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 68, 40)) +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 68, 66)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 68, 77)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 68, 82)) +>2 : Symbol(2, Decl(tupleTypeInference3.ts, 68, 104)) + +f3([1, arg => { }] as const); // Error +>f3 : Symbol(f3, Decl(tupleTypeInference3.ts, 66, 39)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 69, 6)) +>const : Symbol(const) + +declare function f4(_: [(arg: number) => void] | [(arg: string) => void, true]): void; +>f4 : Symbol(f4, Decl(tupleTypeInference3.ts, 69, 29)) +>_ : Symbol(_, Decl(tupleTypeInference3.ts, 71, 20)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 71, 25)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 71, 51)) + +f4([arg => { arg === 0 }] as const); +>f4 : Symbol(f4, Decl(tupleTypeInference3.ts, 69, 29)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 72, 4)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 72, 4)) +>const : Symbol(const) + +declare function f5(arg: { 0: null, 1: (arg: number) => void, foo?: string } | [1, (arg: boolean) => void]): void; +>f5 : Symbol(f5, Decl(tupleTypeInference3.ts, 72, 36)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 74, 20)) +>0 : Symbol(0, Decl(tupleTypeInference3.ts, 74, 26)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 74, 35)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 74, 40)) +>foo : Symbol(foo, Decl(tupleTypeInference3.ts, 74, 61)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 74, 84)) + +f5([null, (arg) => { arg === 0 }] as const); +>f5 : Symbol(f5, Decl(tupleTypeInference3.ts, 72, 36)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 75, 11)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 75, 11)) +>const : Symbol(const) + +f5([1, (arg) => { arg === true }] as const); +>f5 : Symbol(f5, Decl(tupleTypeInference3.ts, 72, 36)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 76, 8)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 76, 8)) +>const : Symbol(const) + +declare function f6(arg: { 1: (arg: number) => void, [k: number]: (...args: never) => void } | [1, (arg: boolean) => void]): void; +>f6 : Symbol(f6, Decl(tupleTypeInference3.ts, 76, 44)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 78, 20)) +>1 : Symbol(1, Decl(tupleTypeInference3.ts, 78, 26)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 78, 31)) +>k : Symbol(k, Decl(tupleTypeInference3.ts, 78, 54)) +>args : Symbol(args, Decl(tupleTypeInference3.ts, 78, 67)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 78, 100)) + +f6([1, (arg) => { }] as const); // Error +>f6 : Symbol(f6, Decl(tupleTypeInference3.ts, 76, 44)) +>arg : Symbol(arg, Decl(tupleTypeInference3.ts, 79, 8)) +>const : Symbol(const) + diff --git a/tests/baselines/reference/tupleTypeInference3.types b/tests/baselines/reference/tupleTypeInference3.types new file mode 100644 index 0000000000000..1d418a1c7ef80 --- /dev/null +++ b/tests/baselines/reference/tupleTypeInference3.types @@ -0,0 +1,891 @@ +//// [tests/cases/compiler/tupleTypeInference3.ts] //// + +=== tupleTypeInference3.ts === +// Repro from #55632 + +type InferArg = +>InferArg : InferArg +> : ^^^^^^^^ + + | [1, (a: number) => void] +>a : number +> : ^^^^^^ + + | [2, (b: string) => void]; +>b : string +> : ^^^^^^ + +const arg: InferArg = [1, (a) => { }]; +>arg : InferArg +> : ^^^^^^^^ +>[1, (a) => { }] : [1, (a: number) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ + +// More tests + +type T1 = [1, (a: number) => void]; +>T1 : T1 +> : ^^ +>a : number +> : ^^^^^^ + +type T2 = { 0: 1, 1: (a: boolean) => void, 2: number }; +>T2 : T2 +> : ^^ +>0 : 1 +> : ^ +>1 : (a: boolean) => void +> : ^ ^^ ^^^^^ +>a : boolean +> : ^^^^^^^ +>2 : number +> : ^^^^^^ + +type T3 = T1 | T2; +>T3 : T3 +> : ^^ + +const v31: T3 = [1, (a) => { a === 0 }]; +>v31 : T3 +> : ^^ +>[1, (a) => { a === 0 }] : [1, (a: number) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === 0 } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>a === 0 : boolean +> : ^^^^^^^ +>a : number +> : ^^^^^^ +>0 : 0 +> : ^ + +const v32: T3 = [1, (a) => { a === true }, 0]; +>v32 : T3 +> : ^^ +>[1, (a) => { a === true }, 0] : [1, (a: boolean) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === true } : (a: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>a === true : boolean +> : ^^^^^^^ +>a : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ +>0 : 0 +> : ^ + +const v33: T3 = [1, (a) => { a === true }, 0, 0]; +>v33 : T3 +> : ^^ +>[1, (a) => { a === true }, 0, 0] : [1, (a: boolean) => void, number, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === true } : (a: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>a === true : boolean +> : ^^^^^^^ +>a : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ +>0 : 0 +> : ^ +>0 : 0 +> : ^ + +const v34: T3 = [1, (a: boolean) => { a === true }]; // Error +>v34 : T3 +> : ^^ +>[1, (a: boolean) => { a === true }] : [1, (a: boolean) => void] +> : ^^^^^ ^^ ^^^^^^^^^^ +>1 : 1 +> : ^ +>(a: boolean) => { a === true } : (a: boolean) => void +> : ^ ^^ ^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>a === true : boolean +> : ^^^^^^^ +>a : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + +type T4 = T3 | [2, (b: string) => void] +>T4 : T4 +> : ^^ +>b : string +> : ^^^^^^ + +const v41: T4 = [1, (a) => { a === 0 }]; +>v41 : T4 +> : ^^ +>[1, (a) => { a === 0 }] : [1, (a: number) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === 0 } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>a === 0 : boolean +> : ^^^^^^^ +>a : number +> : ^^^^^^ +>0 : 0 +> : ^ + +const v42: T4 = [1, (a) => { a === true }, 0]; +>v42 : T4 +> : ^^ +>[1, (a) => { a === true }, 0] : [1, (a: boolean) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === true } : (a: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>a === true : boolean +> : ^^^^^^^ +>a : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ +>0 : 0 +> : ^ + +const v43: T4 = [2, (a) => { a === "" }]; +>v43 : T4 +> : ^^ +>[2, (a) => { a === "" }] : [2, (a: string) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>2 : 2 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ + +type T5 = T4 | {} +>T5 : T5 +> : ^^ + +const v52: T5 = [1, (a) => { a === 0 }]; +>v52 : T5 +> : ^^ +>[1, (a) => { a === 0 }] : [1, (a: number) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === 0 } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>a === 0 : boolean +> : ^^^^^^^ +>a : number +> : ^^^^^^ +>0 : 0 +> : ^ + +const v53: T5 = [1, (a) => { a === true }, 0]; +>v53 : T5 +> : ^^ +>[1, (a) => { a === true }, 0] : [1, (a: boolean) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === true } : (a: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>a === true : boolean +> : ^^^^^^^ +>a : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ +>0 : 0 +> : ^ + +const v54: T5 = [2, (a) => { a === "" }]; +>v54 : T5 +> : ^^ +>[2, (a) => { a === "" }] : [2, (a: string) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>2 : 2 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ + +type T6 = T1 | { 0: 1, 1: (a: boolean) => void, 2?: number } +>T6 : T6 +> : ^^ +>0 : 1 +> : ^ +>1 : (a: boolean) => void +> : ^ ^^ ^^^^^ +>a : boolean +> : ^^^^^^^ +>2 : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + +const v61: T6 = [1, (a) => { a === true }, 0]; +>v61 : T6 +> : ^^ +>[1, (a) => { a === true }, 0] : [1, (a: boolean) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === true } : (a: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>a === true : boolean +> : ^^^^^^^ +>a : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ +>0 : 0 +> : ^ + +const v62: T6 = [1, (a) => { }]; // Error +>v62 : T6 +> : ^^ +>[1, (a) => { }] : [1, (a: any) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { } : (a: any) => void +> : ^ ^^^^^^^^^^^^^^ +>a : any +> : ^^^ + +type T7 = [1, (a: number) => void, ...number[]]; +>T7 : T7 +> : ^^ +>a : number +> : ^^^^^^ + +type T8 = T7 | [1, (a: boolean) => void] +>T8 : T8 +> : ^^ +>a : boolean +> : ^^^^^^^ + +const v81: T8 = [1, (a) => { a === 0 }, 0]; +>v81 : T8 +> : ^^ +>[1, (a) => { a === 0 }, 0] : [1, (a: number) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === 0 } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>a === 0 : boolean +> : ^^^^^^^ +>a : number +> : ^^^^^^ +>0 : 0 +> : ^ +>0 : 0 +> : ^ + +const v82: T8 = [1, (a) => { }]; // Error +>v82 : T8 +> : ^^ +>[1, (a) => { }] : [1, (a: any) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { } : (a: any) => void +> : ^ ^^^^^^^^^^^^^^ +>a : any +> : ^^^ + +type T9 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?]; +>T9 : T9 +> : ^^ +>a : number +> : ^^^^^^ +>b : string +> : ^^^^^^ + +const v91: T9 = [1, (a) => { a === 0 }, 0, ""]; +>v91 : T9 +> : ^^ +>[1, (a) => { a === 0 }, 0, ""] : [1, (a: number) => void, number, string] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === 0 } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>a === 0 : boolean +> : ^^^^^^^ +>a : number +> : ^^^^^^ +>0 : 0 +> : ^ +>0 : 0 +> : ^ +>"" : "" +> : ^^ + +const v92: T9 = [1, (a) => { a === "" }]; +>v92 : T9 +> : ^^ +>[1, (a) => { a === "" }] : [1, (a: string) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const v93: T9 = [1, (a) => { a === "" }, 0]; +>v93 : T9 +> : ^^ +>[1, (a) => { a === "" }, 0] : [1, (a: string) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ +>0 : 0 +> : ^ + +type T10 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, string?]; +>T10 : T10 +> : ^^^ +>a : number +> : ^^^^^^ +>b : string +> : ^^^^^^ + +const v101: T10 = [1, (a) => { a === "" }]; +>v101 : T10 +> : ^^^ +>[1, (a) => { a === "" }] : [1, (a: string) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const v102: T10 = [1, (a) => { a === "" }, 0]; +>v102 : T10 +> : ^^^ +>[1, (a) => { a === "" }, 0] : [1, (a: string) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ +>0 : 0 +> : ^ + +const v103: T10 = [1, (a) => { }, 0, ""]; // Error +>v103 : T10 +> : ^^^ +>[1, (a) => { }, 0, ""] : [1, (a: any) => void, number, string] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { } : (a: any) => void +> : ^ ^^^^^^^^^^^^^^ +>a : any +> : ^^^ +>0 : 0 +> : ^ +>"" : "" +> : ^^ + +type T11 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, boolean?]; +>T11 : T11 +> : ^^^ +>a : number +> : ^^^^^^ +>b : string +> : ^^^^^^ + +const v111: T11 = [1, (a) => { a === "" }]; +>v111 : T11 +> : ^^^ +>[1, (a) => { a === "" }] : [1, (a: string) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ + +const v112: T11 = [1, (a) => { a === "" }, 0]; +>v112 : T11 +> : ^^^ +>[1, (a) => { a === "" }, 0] : [1, (a: string) => void, number] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ +>0 : 0 +> : ^ + +const v113: T11 = [1, (a) => { a === 0 }, 0, ""]; +>v113 : T11 +> : ^^^ +>[1, (a) => { a === 0 }, 0, ""] : [1, (a: number) => void, number, string] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === 0 } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>a === 0 : boolean +> : ^^^^^^^ +>a : number +> : ^^^^^^ +>0 : 0 +> : ^ +>0 : 0 +> : ^ +>"" : "" +> : ^^ + +const v114: T11 = [1, (a) => { a === "" }, 0, true]; +>v114 : T11 +> : ^^^ +>[1, (a) => { a === "" }, 0, true] : [1, (a: string) => void, number, true] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ +>0 : 0 +> : ^ +>true : true +> : ^^^^ + +type T12 = +>T12 : T12 +> : ^^^ + + | { 1: (arg: File) => void } +>1 : (arg: File) => void +> : ^ ^^ ^^^^^ +>arg : File +> : ^^^^ + + | { 0?: number, 1: (arg: Date) => void } +>0 : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>1 : (arg: Date) => void +> : ^ ^^ ^^^^^ +>arg : Date +> : ^^^^ + + | { 0: (arg: boolean) => void } +>0 : (arg: boolean) => void +> : ^ ^^ ^^^^^ +>arg : boolean +> : ^^^^^^^ + + | { 0: boolean, 1: (arg: number) => void } +>0 : boolean +> : ^^^^^^^ +>1 : (arg: number) => void +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ + + | [null, (arg: string) => void]; +>arg : string +> : ^^^^^^ + +declare function f(a: T12): void; +>f : (a: T12) => void +> : ^ ^^ ^^^^^ +>a : T12 +> : ^^^ + +f([null, (a) => { a === "" }]); +>f([null, (a) => { a === "" }]) : void +> : ^^^^ +>f : (a: T12) => void +> : ^ ^^ ^^^^^ +>[null, (a) => { a === "" }] : [null, (a: string) => void] +> : ^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>(a) => { a === "" } : (a: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : string +> : ^^^^^^ +>a === "" : boolean +> : ^^^^^^^ +>a : string +> : ^^^^^^ +>"" : "" +> : ^^ + +f([true, (a) => { a === 0 }]); +>f([true, (a) => { a === 0 }]) : void +> : ^^^^ +>f : (a: T12) => void +> : ^ ^^ ^^^^^ +>[true, (a) => { a === 0 }] : [true, (a: number) => void] +> : ^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>true : true +> : ^^^^ +>(a) => { a === 0 } : (a: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>a : number +> : ^^^^^^ +>a === 0 : boolean +> : ^^^^^^^ +>a : number +> : ^^^^^^ +>0 : 0 +> : ^ + +f([(a) => { a === true }]); +>f([(a) => { a === true }]) : void +> : ^^^^ +>f : (a: T12) => void +> : ^ ^^ ^^^^^ +>[(a) => { a === true }] : [(a: boolean) => void] +> : ^^ ^^^^^^^^^^^^^^^^^^^ +>(a) => { a === true } : (a: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>a : boolean +> : ^^^^^^^ +>a === true : boolean +> : ^^^^^^^ +>a : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + +f([0, (a) => { a as Date }]); +>f([0, (a) => { a as Date }]) : void +> : ^^^^ +>f : (a: T12) => void +> : ^ ^^ ^^^^^ +>[0, (a) => { a as Date }] : [number, (a: Date) => void] +> : ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ +>0 : 0 +> : ^ +>(a) => { a as Date } : (a: Date) => void +> : ^ ^^^^^^^^^^^^^^^ +>a : Date +> : ^^^^ +>a as Date : Date +> : ^^^^ +>a : Date +> : ^^^^ + +f([, (a) => { }]); // Error +>f([, (a) => { }]) : void +> : ^^^^ +>f : (a: T12) => void +> : ^ ^^ ^^^^^ +>[, (a) => { }] : [undefined, (a: any) => void] +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +> : undefined +> : ^^^^^^^^^ +>(a) => { } : (a: any) => void +> : ^ ^^^^^^^^^^^^^^ +>a : any +> : ^^^ + +declare function f2(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2: any }): void; +>f2 : (_: { 0: number; 1: (arg: number) => void; } | { 0: number; 1: (arg: boolean) => void; 2: any; }) => void +> : ^ ^^ ^^^^^ +>_ : { 0: number; 1: (arg: number) => void; } | { 0: number; 1: (arg: boolean) => void; 2: any; } +> : ^^^^^ ^^^^^ ^^^^^^^^^^^ ^^^^^ ^^^^^ ^^^ +>0 : number +> : ^^^^^^ +>1 : (arg: number) => void +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ +>0 : number +> : ^^^^^^ +>1 : (arg: boolean) => void +> : ^ ^^ ^^^^^ +>arg : boolean +> : ^^^^^^^ +>2 : any +> : ^^^ + +f2([1, arg => { arg === 0 }] as const); +>f2([1, arg => { arg === 0 }] as const) : void +> : ^^^^ +>f2 : (_: { 0: number; 1: (arg: number) => void; } | { 0: number; 1: (arg: boolean) => void; 2: any; }) => void +> : ^ ^^ ^^^^^ +>[1, arg => { arg === 0 }] as const : readonly [1, (arg: number) => void] +> : ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>[1, arg => { arg === 0 }] : readonly [1, (arg: number) => void] +> : ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>arg => { arg === 0 } : (arg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg : number +> : ^^^^^^ +>arg === 0 : boolean +> : ^^^^^^^ +>arg : number +> : ^^^^^^ +>0 : 0 +> : ^ + +declare function f3(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2?: any }): void; +>f3 : (_: { 0: number; 1: (arg: number) => void; } | { 0: number; 1: (arg: boolean) => void; 2?: any; }) => void +> : ^ ^^ ^^^^^ +>_ : { 0: number; 1: (arg: number) => void; } | { 0: number; 1: (arg: boolean) => void; 2?: any; } +> : ^^^^^ ^^^^^ ^^^^^^^^^^^ ^^^^^ ^^^^^^ ^^^ +>0 : number +> : ^^^^^^ +>1 : (arg: number) => void +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ +>0 : number +> : ^^^^^^ +>1 : (arg: boolean) => void +> : ^ ^^ ^^^^^ +>arg : boolean +> : ^^^^^^^ +>2 : any +> : ^^^ + +f3([1, arg => { }] as const); // Error +>f3([1, arg => { }] as const) : void +> : ^^^^ +>f3 : (_: { 0: number; 1: (arg: number) => void; } | { 0: number; 1: (arg: boolean) => void; 2?: any; }) => void +> : ^ ^^ ^^^^^ +>[1, arg => { }] as const : readonly [1, (arg: any) => void] +> : ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>[1, arg => { }] : readonly [1, (arg: any) => void] +> : ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>arg => { } : (arg: any) => void +> : ^ ^^^^^^^^^^^^^^ +>arg : any +> : ^^^ + +declare function f4(_: [(arg: number) => void] | [(arg: string) => void, true]): void; +>f4 : (_: [(arg: number) => void] | [(arg: string) => void, true]) => void +> : ^ ^^ ^^^^^ +>_ : [(arg: number) => void] | [(arg: string) => void, true] +> : ^^ ^^ ^^^^^ ^^^^^^ ^^ ^^^^^ ^^^^^^^ +>arg : number +> : ^^^^^^ +>arg : string +> : ^^^^^^ +>true : true +> : ^^^^ + +f4([arg => { arg === 0 }] as const); +>f4([arg => { arg === 0 }] as const) : void +> : ^^^^ +>f4 : (_: [(arg: number) => void] | [(arg: string) => void, true]) => void +> : ^ ^^ ^^^^^ +>[arg => { arg === 0 }] as const : [(arg: number) => void] +> : ^^ ^^^^^^^^^^^^^^^^^^ +>[arg => { arg === 0 }] : [(arg: number) => void] +> : ^^ ^^^^^^^^^^^^^^^^^^ +>arg => { arg === 0 } : (arg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg : number +> : ^^^^^^ +>arg === 0 : boolean +> : ^^^^^^^ +>arg : number +> : ^^^^^^ +>0 : 0 +> : ^ + +declare function f5(arg: { 0: null, 1: (arg: number) => void, foo?: string } | [1, (arg: boolean) => void]): void; +>f5 : (arg: { 0: null; 1: (arg: number) => void; foo?: string; } | [1, (arg: boolean) => void]) => void +> : ^ ^^ ^^^^^ +>arg : { 0: null; 1: (arg: number) => void; foo?: string; } | [1, (arg: boolean) => void] +> : ^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ ^ +>0 : null +> : ^^^^ +>1 : (arg: number) => void +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ +>foo : string | undefined +> : ^^^^^^^^^^^^^^^^^^ +>arg : boolean +> : ^^^^^^^ + +f5([null, (arg) => { arg === 0 }] as const); +>f5([null, (arg) => { arg === 0 }] as const) : void +> : ^^^^ +>f5 : (arg: { 0: null; 1: (arg: number) => void; foo?: string; } | [1, (arg: boolean) => void]) => void +> : ^ ^^ ^^^^^ +>[null, (arg) => { arg === 0 }] as const : readonly [null, (arg: number) => void] +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>[null, (arg) => { arg === 0 }] : readonly [null, (arg: number) => void] +> : ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>(arg) => { arg === 0 } : (arg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg : number +> : ^^^^^^ +>arg === 0 : boolean +> : ^^^^^^^ +>arg : number +> : ^^^^^^ +>0 : 0 +> : ^ + +f5([1, (arg) => { arg === true }] as const); +>f5([1, (arg) => { arg === true }] as const) : void +> : ^^^^ +>f5 : (arg: { 0: null; 1: (arg: number) => void; foo?: string; } | [1, (arg: boolean) => void]) => void +> : ^ ^^ ^^^^^ +>[1, (arg) => { arg === true }] as const : [1, (arg: boolean) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^ +>[1, (arg) => { arg === true }] : [1, (arg: boolean) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(arg) => { arg === true } : (arg: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>arg : boolean +> : ^^^^^^^ +>arg === true : boolean +> : ^^^^^^^ +>arg : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + +declare function f6(arg: { 1: (arg: number) => void, [k: number]: (...args: never) => void } | [1, (arg: boolean) => void]): void; +>f6 : (arg: { 1: (arg: number) => void; [k: number]: (...args: never) => void; } | [1, (arg: boolean) => void]) => void +> : ^ ^^ ^^^^^ +>arg : { [k: number]: (...args: never) => void; 1: (arg: number) => void; } | [1, (arg: boolean) => void] +> : ^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ ^ +>1 : (arg: number) => void +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ +>k : number +> : ^^^^^^ +>args : never +> : ^^^^^ +>arg : boolean +> : ^^^^^^^ + +f6([1, (arg) => { }] as const); // Error +>f6([1, (arg) => { }] as const) : void +> : ^^^^ +>f6 : (arg: { 1: (arg: number) => void; [k: number]: (...args: never) => void; } | [1, (arg: boolean) => void]) => void +> : ^ ^^ ^^^^^ +>[1, (arg) => { }] as const : [1, (arg: any) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^ +>[1, (arg) => { }] : [1, (arg: any) => void] +> : ^^^^^ ^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ +>(arg) => { } : (arg: any) => void +> : ^ ^^^^^^^^^^^^^^ +>arg : any +> : ^^^ + diff --git a/tests/cases/compiler/tupleTypeInference3.ts b/tests/cases/compiler/tupleTypeInference3.ts new file mode 100644 index 0000000000000..4d0cc39c11307 --- /dev/null +++ b/tests/cases/compiler/tupleTypeInference3.ts @@ -0,0 +1,82 @@ +// @strict: true + +// Repro from #55632 + +type InferArg = + | [1, (a: number) => void] + | [2, (b: string) => void]; +const arg: InferArg = [1, (a) => { }]; + +// More tests + +type T1 = [1, (a: number) => void]; +type T2 = { 0: 1, 1: (a: boolean) => void, 2: number }; +type T3 = T1 | T2; +const v31: T3 = [1, (a) => { a === 0 }]; +const v32: T3 = [1, (a) => { a === true }, 0]; +const v33: T3 = [1, (a) => { a === true }, 0, 0]; +const v34: T3 = [1, (a: boolean) => { a === true }]; // Error + +type T4 = T3 | [2, (b: string) => void] +const v41: T4 = [1, (a) => { a === 0 }]; +const v42: T4 = [1, (a) => { a === true }, 0]; +const v43: T4 = [2, (a) => { a === "" }]; + +type T5 = T4 | {} +const v52: T5 = [1, (a) => { a === 0 }]; +const v53: T5 = [1, (a) => { a === true }, 0]; +const v54: T5 = [2, (a) => { a === "" }]; + +type T6 = T1 | { 0: 1, 1: (a: boolean) => void, 2?: number } +const v61: T6 = [1, (a) => { a === true }, 0]; +const v62: T6 = [1, (a) => { }]; // Error + +type T7 = [1, (a: number) => void, ...number[]]; +type T8 = T7 | [1, (a: boolean) => void] +const v81: T8 = [1, (a) => { a === 0 }, 0]; +const v82: T8 = [1, (a) => { }]; // Error + +type T9 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?]; +const v91: T9 = [1, (a) => { a === 0 }, 0, ""]; +const v92: T9 = [1, (a) => { a === "" }]; +const v93: T9 = [1, (a) => { a === "" }, 0]; + +type T10 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, string?]; +const v101: T10 = [1, (a) => { a === "" }]; +const v102: T10 = [1, (a) => { a === "" }, 0]; +const v103: T10 = [1, (a) => { }, 0, ""]; // Error + +type T11 = [1, (a: number) => void, ...[number, string]] | [1, (b: string) => void, number?, boolean?]; +const v111: T11 = [1, (a) => { a === "" }]; +const v112: T11 = [1, (a) => { a === "" }, 0]; +const v113: T11 = [1, (a) => { a === 0 }, 0, ""]; +const v114: T11 = [1, (a) => { a === "" }, 0, true]; + +type T12 = + | { 1: (arg: File) => void } + | { 0?: number, 1: (arg: Date) => void } + | { 0: (arg: boolean) => void } + | { 0: boolean, 1: (arg: number) => void } + | [null, (arg: string) => void]; +declare function f(a: T12): void; +f([null, (a) => { a === "" }]); +f([true, (a) => { a === 0 }]); +f([(a) => { a === true }]); +f([0, (a) => { a as Date }]); +f([, (a) => { }]); // Error + +declare function f2(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2: any }): void; +f2([1, arg => { arg === 0 }] as const); + +declare function f3(_: { 0: number, 1: (arg: number) => void } | { 0: number, 1: (arg: boolean) => void, 2?: any }): void; +f3([1, arg => { }] as const); // Error + +declare function f4(_: [(arg: number) => void] | [(arg: string) => void, true]): void; +f4([arg => { arg === 0 }] as const); + +declare function f5(arg: { 0: null, 1: (arg: number) => void, foo?: string } | [1, (arg: boolean) => void]): void; +f5([null, (arg) => { arg === 0 }] as const); +f5([1, (arg) => { arg === true }] as const); + +declare function f6(arg: { 1: (arg: number) => void, [k: number]: (...args: never) => void } | [1, (arg: boolean) => void]): void; +f6([1, (arg) => { }] as const); // Error \ No newline at end of file