diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fa7585791277b..480e4fa2e8563 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19541,18 +19541,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } const moreThanOneRealChildren = length(validChildren) > 1; - let arrayLikeTargetParts: Type; - let nonArrayLikeTargetParts: Type; - const iterableType = getGlobalIterableType(/*reportErrors*/ false); - if (iterableType !== emptyGenericType) { - const anyIterable = createIterableType(anyType); - arrayLikeTargetParts = filterType(childrenTargetType, t => isTypeAssignableTo(t, anyIterable)); - nonArrayLikeTargetParts = filterType(childrenTargetType, t => !isTypeAssignableTo(t, anyIterable)); - } - else { - arrayLikeTargetParts = filterType(childrenTargetType, isArrayOrTupleLikeType); - nonArrayLikeTargetParts = filterType(childrenTargetType, t => !isArrayOrTupleLikeType(t)); - } + const arrayLikeTargetParts = filterType(childrenTargetType, isAssignableToAvailableAnyIterable); + const nonArrayLikeTargetParts = filterType(childrenTargetType, t => !isAssignableToAvailableAnyIterable(t)); if (moreThanOneRealChildren) { if (arrayLikeTargetParts !== neverType) { const realSource = createTupleType(checkJsxChildren(containingElement, CheckMode.Normal)); @@ -23075,6 +23065,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isArrayLikeType(type) || isTupleLikeType(type); } + function isAssignableToAvailableAnyIterable(type: Type): boolean { + const anyIterable = getGlobalIterableType(/*reportErrors*/ false) !== emptyGenericType && createIterableType(anyType); + return anyIterable ? isTypeAssignableTo(type, anyIterable) : isArrayOrTupleLikeType(type); + } + function getTupleElementType(type: Type, index: number) { const propType = getTypeOfPropertyOfType(type, "" + index as __String); if (propType) { @@ -29034,7 +29029,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // type of T. function getContextualTypeForElementExpression(arrayContextualType: Type | undefined, index: number): Type | undefined { return arrayContextualType && ( - index >= 0 && getTypeOfPropertyOfContextualType(arrayContextualType, "" + index as __String) || + index >= 0 && getTypeOfPropertyOfContextualType(filterType(arrayContextualType, t => !!getIndexTypeOfType(t, numberType) || isAssignableToAvailableAnyIterable(t)), "" + index as __String) || mapType(arrayContextualType, t => isTupleType(t) ? getElementTypeOfSliceOfTupleType(t, 0, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true) : diff --git a/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.symbols b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.symbols new file mode 100644 index 0000000000000..b0ff34c16170b --- /dev/null +++ b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts === +// repro from #52588 + +declare function test( +>test : Symbol(test, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts, 0, 0)) + + arg: Record void> | Array<(arg: number) => void> +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts, 2, 22)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts, 3, 23)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts, 3, 54)) + +): void; + +test([ +>test : Symbol(test, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts, 0, 0)) + + (arg) => { +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts, 7, 3)) + + arg; // number +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts, 7, 3)) + + }, +]); + diff --git a/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.types b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.types new file mode 100644 index 0000000000000..c7c6d9c096f61 --- /dev/null +++ b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts === +// repro from #52588 + +declare function test( +>test : (arg: Record void> | ((arg: number) => void)[]) => void + + arg: Record void> | Array<(arg: number) => void> +>arg : Record void> | ((arg: number) => void)[] +>arg : string +>arg : number + +): void; + +test([ +>test([ (arg) => { arg; // number },]) : void +>test : (arg: Record void> | ((arg: number) => void)[]) => void +>[ (arg) => { arg; // number },] : ((arg: number) => void)[] + + (arg) => { +>(arg) => { arg; // number } : (arg: number) => void +>arg : number + + arg; // number +>arg : number + + }, +]); + diff --git a/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.symbols b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.symbols new file mode 100644 index 0000000000000..cb803d9186e96 --- /dev/null +++ b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts === +// repro from #52588 + +declare function test( +>test : Symbol(test, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts, 0, 0)) + + arg: Record void> | Array<(arg: number) => void> +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts, 2, 22)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts, 3, 23)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts, 3, 54)) + +): void; + +test([ +>test : Symbol(test, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts, 0, 0)) + + (arg) => { +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts, 7, 3)) + + arg; // number +>arg : Symbol(arg, Decl(contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts, 7, 3)) + + }, +]); + diff --git a/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.types b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.types new file mode 100644 index 0000000000000..04c1ea69a2789 --- /dev/null +++ b/tests/baselines/reference/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts === +// repro from #52588 + +declare function test( +>test : (arg: Record void> | ((arg: number) => void)[]) => void + + arg: Record void> | Array<(arg: number) => void> +>arg : Record void> | ((arg: number) => void)[] +>arg : string +>arg : number + +): void; + +test([ +>test([ (arg) => { arg; // number },]) : void +>test : (arg: Record void> | ((arg: number) => void)[]) => void +>[ (arg) => { arg; // number },] : ((arg: number) => void)[] + + (arg) => { +>(arg) => { arg; // number } : (arg: number) => void +>arg : number + + arg; // number +>arg : number + + }, +]); + diff --git a/tests/baselines/reference/contextualTypeCaching.symbols b/tests/baselines/reference/contextualTypeCaching.symbols index 24122b7afddd5..2550a1e5ff02e 100644 --- a/tests/baselines/reference/contextualTypeCaching.symbols +++ b/tests/baselines/reference/contextualTypeCaching.symbols @@ -60,3 +60,70 @@ emit('a', { }, }); +// simplified repro from 52589#issuecomment-1416180638 +declare class MyCompiler { +>MyCompiler : Symbol(MyCompiler, Decl(contextualTypeCaching.ts, 21, 3)) + + compile(): void; +>compile : Symbol(MyCompiler.compile, Decl(contextualTypeCaching.ts, 24, 26)) +} +interface WebpackPluginInstance { +>WebpackPluginInstance : Symbol(WebpackPluginInstance, Decl(contextualTypeCaching.ts, 26, 1)) + + apply: (compiler: MyCompiler) => void; +>apply : Symbol(WebpackPluginInstance.apply, Decl(contextualTypeCaching.ts, 27, 33)) +>compiler : Symbol(compiler, Decl(contextualTypeCaching.ts, 28, 10)) +>MyCompiler : Symbol(MyCompiler, Decl(contextualTypeCaching.ts, 21, 3)) +} +type WebpackPluginFunction = (this: MyCompiler, compiler: MyCompiler) => void; +>WebpackPluginFunction : Symbol(WebpackPluginFunction, Decl(contextualTypeCaching.ts, 29, 1)) +>this : Symbol(this, Decl(contextualTypeCaching.ts, 30, 30)) +>MyCompiler : Symbol(MyCompiler, Decl(contextualTypeCaching.ts, 21, 3)) +>compiler : Symbol(compiler, Decl(contextualTypeCaching.ts, 30, 47)) +>MyCompiler : Symbol(MyCompiler, Decl(contextualTypeCaching.ts, 21, 3)) + +interface Optimization { +>Optimization : Symbol(Optimization, Decl(contextualTypeCaching.ts, 30, 78)) + + minimizer?: (WebpackPluginInstance | WebpackPluginFunction)[]; +>minimizer : Symbol(Optimization.minimizer, Decl(contextualTypeCaching.ts, 31, 24)) +>WebpackPluginInstance : Symbol(WebpackPluginInstance, Decl(contextualTypeCaching.ts, 26, 1)) +>WebpackPluginFunction : Symbol(WebpackPluginFunction, Decl(contextualTypeCaching.ts, 29, 1)) +} +declare const A: ( +>A : Symbol(A, Decl(contextualTypeCaching.ts, 34, 13)) +>T : Symbol(T, Decl(contextualTypeCaching.ts, 34, 18)) +>P : Symbol(P, Decl(contextualTypeCaching.ts, 34, 20)) +>T : Symbol(T, Decl(contextualTypeCaching.ts, 34, 18)) + + obj: T, +>obj : Symbol(obj, Decl(contextualTypeCaching.ts, 34, 40)) +>T : Symbol(T, Decl(contextualTypeCaching.ts, 34, 18)) + + prop: P, +>prop : Symbol(prop, Decl(contextualTypeCaching.ts, 35, 9)) +>P : Symbol(P, Decl(contextualTypeCaching.ts, 34, 20)) + + factory: () => T[P] +>factory : Symbol(factory, Decl(contextualTypeCaching.ts, 36, 10)) +>T : Symbol(T, Decl(contextualTypeCaching.ts, 34, 18)) +>P : Symbol(P, Decl(contextualTypeCaching.ts, 34, 20)) + +) => void; +export const applyOptimizationDefaults = (optimization: Optimization) => { +>applyOptimizationDefaults : Symbol(applyOptimizationDefaults, Decl(contextualTypeCaching.ts, 39, 12)) +>optimization : Symbol(optimization, Decl(contextualTypeCaching.ts, 39, 42)) +>Optimization : Symbol(Optimization, Decl(contextualTypeCaching.ts, 30, 78)) + + A(optimization, "minimizer", () => [ +>A : Symbol(A, Decl(contextualTypeCaching.ts, 34, 13)) +>optimization : Symbol(optimization, Decl(contextualTypeCaching.ts, 39, 42)) + { + apply: (compiler) => {}, +>apply : Symbol(apply, Decl(contextualTypeCaching.ts, 41, 5)) +>compiler : Symbol(compiler, Decl(contextualTypeCaching.ts, 42, 14)) + + }, + ]); +}; + diff --git a/tests/baselines/reference/contextualTypeCaching.types b/tests/baselines/reference/contextualTypeCaching.types index 16c99d04e16d2..8b898dcb2e0ee 100644 --- a/tests/baselines/reference/contextualTypeCaching.types +++ b/tests/baselines/reference/contextualTypeCaching.types @@ -54,3 +54,61 @@ emit('a', { }, }); +// simplified repro from 52589#issuecomment-1416180638 +declare class MyCompiler { +>MyCompiler : MyCompiler + + compile(): void; +>compile : () => void +} +interface WebpackPluginInstance { + apply: (compiler: MyCompiler) => void; +>apply : (compiler: MyCompiler) => void +>compiler : MyCompiler +} +type WebpackPluginFunction = (this: MyCompiler, compiler: MyCompiler) => void; +>WebpackPluginFunction : (this: MyCompiler, compiler: MyCompiler) => void +>this : MyCompiler +>compiler : MyCompiler + +interface Optimization { + minimizer?: (WebpackPluginInstance | WebpackPluginFunction)[]; +>minimizer : (WebpackPluginInstance | WebpackPluginFunction)[] | undefined +} +declare const A: ( +>A : (obj: T, prop: P, factory: () => T[P]) => void + + obj: T, +>obj : T + + prop: P, +>prop : P + + factory: () => T[P] +>factory : () => T[P] + +) => void; +export const applyOptimizationDefaults = (optimization: Optimization) => { +>applyOptimizationDefaults : (optimization: Optimization) => void +>(optimization: Optimization) => { A(optimization, "minimizer", () => [ { apply: (compiler) => {}, }, ]);} : (optimization: Optimization) => void +>optimization : Optimization + + A(optimization, "minimizer", () => [ +>A(optimization, "minimizer", () => [ { apply: (compiler) => {}, }, ]) : void +>A : (obj: T, prop: P, factory: () => T[P]) => void +>optimization : Optimization +>"minimizer" : "minimizer" +>() => [ { apply: (compiler) => {}, }, ] : () => { apply: (compiler: MyCompiler) => void; }[] +>[ { apply: (compiler) => {}, }, ] : { apply: (compiler: MyCompiler) => void; }[] + { +>{ apply: (compiler) => {}, } : { apply: (compiler: MyCompiler) => void; } + + apply: (compiler) => {}, +>apply : (compiler: MyCompiler) => void +>(compiler) => {} : (compiler: MyCompiler) => void +>compiler : MyCompiler + + }, + ]); +}; + diff --git a/tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts b/tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts new file mode 100644 index 0000000000000..ff53d21e895ba --- /dev/null +++ b/tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs2015.ts @@ -0,0 +1,15 @@ +// @strict: true +// @noEmit: true +// @lib: es2015 + +// repro from #52588 + +declare function test( + arg: Record void> | Array<(arg: number) => void> +): void; + +test([ + (arg) => { + arg; // number + }, +]); diff --git a/tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts b/tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts new file mode 100644 index 0000000000000..340bd7690578c --- /dev/null +++ b/tests/cases/compiler/contextualSignatureInArrayElementPrefersArrayUnionMemberLibEs5.ts @@ -0,0 +1,15 @@ +// @strict: true +// @noEmit: true +// @lib: es5 + +// repro from #52588 + +declare function test( + arg: Record void> | Array<(arg: number) => void> +): void; + +test([ + (arg) => { + arg; // number + }, +]); diff --git a/tests/cases/compiler/contextualTypeCaching.ts b/tests/cases/compiler/contextualTypeCaching.ts index 542a98724e56a..d8b56d68914b1 100644 --- a/tests/cases/compiler/contextualTypeCaching.ts +++ b/tests/cases/compiler/contextualTypeCaching.ts @@ -23,3 +23,27 @@ emit('a', { nestedCallback: (r) => {}, }, }); + +// simplified repro from 52589#issuecomment-1416180638 +declare class MyCompiler { + compile(): void; +} +interface WebpackPluginInstance { + apply: (compiler: MyCompiler) => void; +} +type WebpackPluginFunction = (this: MyCompiler, compiler: MyCompiler) => void; +interface Optimization { + minimizer?: (WebpackPluginInstance | WebpackPluginFunction)[]; +} +declare const A: ( + obj: T, + prop: P, + factory: () => T[P] +) => void; +export const applyOptimizationDefaults = (optimization: Optimization) => { + A(optimization, "minimizer", () => [ + { + apply: (compiler) => {}, + }, + ]); +};