Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter signatures by matching constraints when instantiating them for instantiation signatures #51695

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37142,8 +37142,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;
});
Expand Down
10 changes: 10 additions & 0 deletions tests/baselines/reference/instantiationExpressions.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,14 @@ instantiationExpressions.ts(164,40): error TS2344: Type 'U' does not satisfy the

type T50<U extends string> = typeof g3<U>; // (a: U) => U
type T51<U extends number> = typeof g3<U, any>; // (b: U) => U

// repro #47607#issuecomment-1331744280

type DivElement = { type: 'div' }
interface ElementMap { div: DivElement }

declare function foo<T extends keyof ElementMap>(arg: T): ElementMap[T];
declare function foo<T extends DivElement>(arg: T): T;

type DivFromMap = typeof foo<"div">;

19 changes: 19 additions & 0 deletions tests/baselines/reference/instantiationExpressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@ declare const g3: {

type T50<U extends string> = typeof g3<U>; // (a: U) => U
type T51<U extends number> = typeof g3<U, any>; // (b: U) => U

// repro #47607#issuecomment-1331744280

type DivElement = { type: 'div' }
interface ElementMap { div: DivElement }

declare function foo<T extends keyof ElementMap>(arg: T): ElementMap[T];
declare function foo<T extends DivElement>(arg: T): T;

type DivFromMap = typeof foo<"div">;


//// [instantiationExpressions.js]
Expand Down Expand Up @@ -382,3 +392,12 @@ declare const g3: {
};
type T50<U extends string> = typeof g3<U>;
type T51<U extends number> = typeof g3<U, any>;
type DivElement = {
type: 'div';
};
interface ElementMap {
div: DivElement;
}
declare function foo<T extends keyof ElementMap>(arg: T): ElementMap[T];
declare function foo<T extends DivElement>(arg: T): T;
type DivFromMap = typeof foo<"div">;
32 changes: 32 additions & 0 deletions tests/baselines/reference/instantiationExpressions.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -650,3 +650,35 @@ type T51<U extends number> = typeof g3<U, any>; // (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<T extends keyof ElementMap>(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<T extends DivElement>(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))

30 changes: 30 additions & 0 deletions tests/baselines/reference/instantiationExpressions.types
Original file line number Diff line number Diff line change
Expand Up @@ -802,3 +802,33 @@ type T51<U extends number> = typeof g3<U, any>; // (b: U) => U
>g3 : { <T extends string>(a: T): T; new <T extends number, Q>(b: T): T; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^ ^^ ^^^ ^^^

// repro #47607#issuecomment-1331744280

type DivElement = { type: 'div' }
>DivElement : DivElement
> : ^^^^^^^^^^
>type : "div"
> : ^^^^^

interface ElementMap { div: DivElement }
>div : DivElement
> : ^^^^^^^^^^

declare function foo<T extends keyof ElementMap>(arg: T): ElementMap[T];
>foo : { <T extends keyof ElementMap>(arg: T): ElementMap[T]; <T_1 extends DivElement>(arg: T_1): T_1; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^^ ^^^^^^^^^^^^^^^ ^^ ^^ ^^^ ^^^
>arg : T
> : ^

declare function foo<T extends DivElement>(arg: T): T;
>foo : { <T_1 extends keyof ElementMap>(arg: T_1): ElementMap[T_1]; <T extends DivElement>(arg: T): T; }
> : ^^^^^^^^^^^^^^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^^ ^^^
>arg : T
> : ^

type DivFromMap = typeof foo<"div">;
>DivFromMap : typeof foo<"div">
> :
>foo : { <T extends keyof ElementMap>(arg: T): ElementMap[T]; <T extends DivElement>(arg: T): T; }
> : ^^^ ^^^^^^^^^ ^^ ^^ ^^^ ^^^ ^^^^^^^^^ ^^ ^^ ^^^ ^^^

Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,13 @@ declare const g3: {

type T50<U extends string> = typeof g3<U>; // (a: U) => U
type T51<U extends number> = typeof g3<U, any>; // (b: U) => U

// repro #47607#issuecomment-1331744280

type DivElement = { type: 'div' }
interface ElementMap { div: DivElement }

declare function foo<T extends keyof ElementMap>(arg: T): ElementMap[T];
declare function foo<T extends DivElement>(arg: T): T;

type DivFromMap = typeof foo<"div">;