From 9e02f0951a474fd41c414dcf0ae73d2336306561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 30 Nov 2022 11:24:00 +0100 Subject: [PATCH] Filter signatures by matching constraints when instantiating them for instantiation signatures --- src/compiler/checker.ts | 14 ++++++-- .../instantiationExpressions.errors.txt | 10 ++++++ .../reference/instantiationExpressions.js | 19 +++++++++++ .../instantiationExpressions.symbols | 32 +++++++++++++++++++ .../reference/instantiationExpressions.types | 21 ++++++++++++ .../instantiationExpressions.ts | 10 ++++++ 6 files changed, 104 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 09b9b57f41c3d..5589261a00879 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -33694,8 +33694,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getInstantiatedSignatures(signatures: readonly Signature[]) { - const applicableSignatures = filter(signatures, sig => !!sig.typeParameters && hasCorrectTypeArgumentArity(sig, typeArguments)); - return sameMap(applicableSignatures, sig => { + const sameTypeAritySignatures = filter(signatures, sig => !!sig.typeParameters && hasCorrectTypeArgumentArity(sig, typeArguments)); + if (!sameTypeAritySignatures.length) { + return sameTypeAritySignatures; + } + const applicableSignatures = mapDefined(sameTypeAritySignatures, sig => { + const typeArgumentTypes = checkTypeArguments(sig, typeArguments!, /*reportErrors*/ false); + return typeArgumentTypes && getSignatureInstantiation(sig, typeArgumentTypes, isInJSFile(sig.declaration)); + }); + if (applicableSignatures.length) { + return applicableSignatures; + } + return sameMap(sameTypeAritySignatures, sig => { const typeArgumentTypes = checkTypeArguments(sig, typeArguments!, /*reportErrors*/ true); return typeArgumentTypes ? getSignatureInstantiation(sig, typeArgumentTypes, isInJSFile(sig.declaration)) : sig; }); diff --git a/tests/baselines/reference/instantiationExpressions.errors.txt b/tests/baselines/reference/instantiationExpressions.errors.txt index d4af975c75fc2..e9127993e8601 100644 --- a/tests/baselines/reference/instantiationExpressions.errors.txt +++ b/tests/baselines/reference/instantiationExpressions.errors.txt @@ -225,4 +225,14 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpr type T50 = typeof g3; // (a: U) => U type T51 = typeof g3; // (b: U) => U + + // repro #47607#issuecomment-1331744280 + + type DivElement = { type: 'div' } + interface ElementMap { div: DivElement } + + declare function foo(arg: T): ElementMap[T]; + declare function foo(arg: T): T; + + type DivFromMap = typeof foo<"div">; \ No newline at end of file diff --git a/tests/baselines/reference/instantiationExpressions.js b/tests/baselines/reference/instantiationExpressions.js index d10ef4b73f3f0..d838d08232812 100644 --- a/tests/baselines/reference/instantiationExpressions.js +++ b/tests/baselines/reference/instantiationExpressions.js @@ -171,6 +171,16 @@ declare const g3: { type T50 = typeof g3; // (a: U) => U type T51 = typeof g3; // (b: U) => U + +// repro #47607#issuecomment-1331744280 + +type DivElement = { type: 'div' } +interface ElementMap { div: DivElement } + +declare function foo(arg: T): ElementMap[T]; +declare function foo(arg: T): T; + +type DivFromMap = typeof foo<"div">; //// [instantiationExpressions.js] @@ -380,3 +390,12 @@ declare const g3: { }; type T50 = typeof g3; type T51 = typeof g3; +type DivElement = { + type: 'div'; +}; +interface ElementMap { + div: DivElement; +} +declare function foo(arg: T): ElementMap[T]; +declare function foo(arg: T): T; +type DivFromMap = typeof foo<"div">; diff --git a/tests/baselines/reference/instantiationExpressions.symbols b/tests/baselines/reference/instantiationExpressions.symbols index 3fd52bf485bc2..bda48de41d74a 100644 --- a/tests/baselines/reference/instantiationExpressions.symbols +++ b/tests/baselines/reference/instantiationExpressions.symbols @@ -648,3 +648,35 @@ type T51 = typeof g3; // (b: U) => U >g3 : Symbol(g3, Decl(instantiationExpressions.ts, 165, 13)) >U : Symbol(U, Decl(instantiationExpressions.ts, 171, 9)) +// repro #47607#issuecomment-1331744280 + +type DivElement = { type: 'div' } +>DivElement : Symbol(DivElement, Decl(instantiationExpressions.ts, 171, 47)) +>type : Symbol(type, Decl(instantiationExpressions.ts, 175, 19)) + +interface ElementMap { div: DivElement } +>ElementMap : Symbol(ElementMap, Decl(instantiationExpressions.ts, 175, 33)) +>div : Symbol(ElementMap.div, Decl(instantiationExpressions.ts, 176, 22)) +>DivElement : Symbol(DivElement, Decl(instantiationExpressions.ts, 171, 47)) + +declare function foo(arg: T): ElementMap[T]; +>foo : Symbol(foo, Decl(instantiationExpressions.ts, 176, 40), Decl(instantiationExpressions.ts, 178, 72)) +>T : Symbol(T, Decl(instantiationExpressions.ts, 178, 21)) +>ElementMap : Symbol(ElementMap, Decl(instantiationExpressions.ts, 175, 33)) +>arg : Symbol(arg, Decl(instantiationExpressions.ts, 178, 49)) +>T : Symbol(T, Decl(instantiationExpressions.ts, 178, 21)) +>ElementMap : Symbol(ElementMap, Decl(instantiationExpressions.ts, 175, 33)) +>T : Symbol(T, Decl(instantiationExpressions.ts, 178, 21)) + +declare function foo(arg: T): T; +>foo : Symbol(foo, Decl(instantiationExpressions.ts, 176, 40), Decl(instantiationExpressions.ts, 178, 72)) +>T : Symbol(T, Decl(instantiationExpressions.ts, 179, 21)) +>DivElement : Symbol(DivElement, Decl(instantiationExpressions.ts, 171, 47)) +>arg : Symbol(arg, Decl(instantiationExpressions.ts, 179, 43)) +>T : Symbol(T, Decl(instantiationExpressions.ts, 179, 21)) +>T : Symbol(T, Decl(instantiationExpressions.ts, 179, 21)) + +type DivFromMap = typeof foo<"div">; +>DivFromMap : Symbol(DivFromMap, Decl(instantiationExpressions.ts, 179, 54)) +>foo : Symbol(foo, Decl(instantiationExpressions.ts, 176, 40), Decl(instantiationExpressions.ts, 178, 72)) + diff --git a/tests/baselines/reference/instantiationExpressions.types b/tests/baselines/reference/instantiationExpressions.types index 75fe72fc441bc..0078687c36c0b 100644 --- a/tests/baselines/reference/instantiationExpressions.types +++ b/tests/baselines/reference/instantiationExpressions.types @@ -514,3 +514,24 @@ type T51 = typeof g3; // (b: U) => U >T51 : new (b: U) => U >g3 : { (a: T): T; new (b: T): T; } +// repro #47607#issuecomment-1331744280 + +type DivElement = { type: 'div' } +>DivElement : { type: 'div'; } +>type : "div" + +interface ElementMap { div: DivElement } +>div : DivElement + +declare function foo(arg: T): ElementMap[T]; +>foo : { (arg: T): ElementMap[T]; (arg: T): T; } +>arg : T + +declare function foo(arg: T): T; +>foo : { (arg: T): ElementMap[T]; (arg: T): T; } +>arg : T + +type DivFromMap = typeof foo<"div">; +>DivFromMap : (arg: "div") => DivElement +>foo : { (arg: T): ElementMap[T]; (arg: T): T; } + diff --git a/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressions.ts b/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressions.ts index ce9d23aacc96d..a053e20009a03 100644 --- a/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressions.ts +++ b/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressions.ts @@ -173,3 +173,13 @@ declare const g3: { type T50 = typeof g3; // (a: U) => U type T51 = typeof g3; // (b: U) => U + +// repro #47607#issuecomment-1331744280 + +type DivElement = { type: 'div' } +interface ElementMap { div: DivElement } + +declare function foo(arg: T): ElementMap[T]; +declare function foo(arg: T): T; + +type DivFromMap = typeof foo<"div">;