From 10b240cde3ab3bfe95fa09275760389c082a4a80 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 22 Sep 2020 21:21:13 -0700 Subject: [PATCH] Allow an infer type node to resolve its own name (#40483) --- src/compiler/checker.ts | 9 +++ ...declarationEmitShadowingInferNotRenamed.js | 40 +++++++++++++ ...rationEmitShadowingInferNotRenamed.symbols | 58 +++++++++++++++++++ ...larationEmitShadowingInferNotRenamed.types | 40 +++++++++++++ ...declarationEmitShadowingInferNotRenamed.ts | 22 +++++++ 5 files changed, 169 insertions(+) create mode 100644 tests/baselines/reference/declarationEmitShadowingInferNotRenamed.js create mode 100644 tests/baselines/reference/declarationEmitShadowingInferNotRenamed.symbols create mode 100644 tests/baselines/reference/declarationEmitShadowingInferNotRenamed.types create mode 100644 tests/cases/compiler/declarationEmitShadowingInferNotRenamed.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 947ecc6e1ff..2e1ed38efe0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1954,6 +1954,15 @@ namespace ts { } } break; + case SyntaxKind.InferType: + if (meaning & SymbolFlags.TypeParameter) { + const parameterName = (location).typeParameter.name; + if (parameterName && name === parameterName.escapedText) { + result = (location).typeParameter.symbol; + break loop; + } + } + break; } if (isSelfReferenceLocation(location)) { lastSelfReferenceLocation = location; diff --git a/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.js b/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.js new file mode 100644 index 00000000000..d69903c0413 --- /dev/null +++ b/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.js @@ -0,0 +1,40 @@ +//// [declarationEmitShadowingInferNotRenamed.ts] +// Any instance type +type Client = string + +// Modified instance +type UpdatedClient = C & {foo: number} + +export const createClient = < + D extends + | (new (...args: any[]) => Client) // accept class + | Record Client> // or map of classes +>( + clientDef: D +): D extends new (...args: any[]) => infer C + ? UpdatedClient // return instance + : { + [K in keyof D]: D[K] extends new (...args: any[]) => infer C // or map of instances respectively + ? UpdatedClient + : never + } => { + return null as any +} + +//// [declarationEmitShadowingInferNotRenamed.js] +"use strict"; +exports.__esModule = true; +exports.createClient = void 0; +var createClient = function (clientDef) { + return null; +}; +exports.createClient = createClient; + + +//// [declarationEmitShadowingInferNotRenamed.d.ts] +declare type Client = string; +declare type UpdatedClient = C & { + foo: number; +}; +export declare const createClient: Client> | (new (...args: any[]) => Client)>(clientDef: D) => D extends new (...args: any[]) => infer C ? UpdatedClient : { [K in keyof D]: D[K] extends new (...args: any[]) => infer C_1 ? UpdatedClient : never; }; +export {}; diff --git a/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.symbols b/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.symbols new file mode 100644 index 00000000000..923c839a7bc --- /dev/null +++ b/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.symbols @@ -0,0 +1,58 @@ +=== tests/cases/compiler/declarationEmitShadowingInferNotRenamed.ts === +// Any instance type +type Client = string +>Client : Symbol(Client, Decl(declarationEmitShadowingInferNotRenamed.ts, 0, 0)) + +// Modified instance +type UpdatedClient = C & {foo: number} +>UpdatedClient : Symbol(UpdatedClient, Decl(declarationEmitShadowingInferNotRenamed.ts, 1, 20)) +>C : Symbol(C, Decl(declarationEmitShadowingInferNotRenamed.ts, 4, 19)) +>C : Symbol(C, Decl(declarationEmitShadowingInferNotRenamed.ts, 4, 19)) +>foo : Symbol(foo, Decl(declarationEmitShadowingInferNotRenamed.ts, 4, 29)) + +export const createClient = < +>createClient : Symbol(createClient, Decl(declarationEmitShadowingInferNotRenamed.ts, 6, 12)) + + D extends +>D : Symbol(D, Decl(declarationEmitShadowingInferNotRenamed.ts, 6, 29)) + + | (new (...args: any[]) => Client) // accept class +>args : Symbol(args, Decl(declarationEmitShadowingInferNotRenamed.ts, 8, 12)) +>Client : Symbol(Client, Decl(declarationEmitShadowingInferNotRenamed.ts, 0, 0)) + + | Record Client> // or map of classes +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(declarationEmitShadowingInferNotRenamed.ts, 9, 26)) +>Client : Symbol(Client, Decl(declarationEmitShadowingInferNotRenamed.ts, 0, 0)) + +>( + clientDef: D +>clientDef : Symbol(clientDef, Decl(declarationEmitShadowingInferNotRenamed.ts, 10, 2)) +>D : Symbol(D, Decl(declarationEmitShadowingInferNotRenamed.ts, 6, 29)) + +): D extends new (...args: any[]) => infer C +>D : Symbol(D, Decl(declarationEmitShadowingInferNotRenamed.ts, 6, 29)) +>args : Symbol(args, Decl(declarationEmitShadowingInferNotRenamed.ts, 12, 18)) +>C : Symbol(C, Decl(declarationEmitShadowingInferNotRenamed.ts, 12, 42)) + + ? UpdatedClient // return instance +>UpdatedClient : Symbol(UpdatedClient, Decl(declarationEmitShadowingInferNotRenamed.ts, 1, 20)) +>C : Symbol(C, Decl(declarationEmitShadowingInferNotRenamed.ts, 12, 42)) + + : { + [K in keyof D]: D[K] extends new (...args: any[]) => infer C // or map of instances respectively +>K : Symbol(K, Decl(declarationEmitShadowingInferNotRenamed.ts, 15, 7)) +>D : Symbol(D, Decl(declarationEmitShadowingInferNotRenamed.ts, 6, 29)) +>D : Symbol(D, Decl(declarationEmitShadowingInferNotRenamed.ts, 6, 29)) +>K : Symbol(K, Decl(declarationEmitShadowingInferNotRenamed.ts, 15, 7)) +>args : Symbol(args, Decl(declarationEmitShadowingInferNotRenamed.ts, 15, 40)) +>C : Symbol(C, Decl(declarationEmitShadowingInferNotRenamed.ts, 15, 64)) + + ? UpdatedClient +>UpdatedClient : Symbol(UpdatedClient, Decl(declarationEmitShadowingInferNotRenamed.ts, 1, 20)) +>C : Symbol(C, Decl(declarationEmitShadowingInferNotRenamed.ts, 15, 64)) + + : never + } => { + return null as any +} diff --git a/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.types b/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.types new file mode 100644 index 00000000000..850a5565891 --- /dev/null +++ b/tests/baselines/reference/declarationEmitShadowingInferNotRenamed.types @@ -0,0 +1,40 @@ +=== tests/cases/compiler/declarationEmitShadowingInferNotRenamed.ts === +// Any instance type +type Client = string +>Client : string + +// Modified instance +type UpdatedClient = C & {foo: number} +>UpdatedClient : UpdatedClient +>foo : number + +export const createClient = < +>createClient : Client> | (new (...args: any[]) => Client)>(clientDef: D) => D extends new (...args: any[]) => infer C ? UpdatedClient : { [K in keyof D]: D[K] extends new (...args: any[]) => infer C ? UpdatedClient : never; } +>< D extends | (new (...args: any[]) => Client) // accept class | Record Client> // or map of classes>( clientDef: D): D extends new (...args: any[]) => infer C ? UpdatedClient // return instance : { [K in keyof D]: D[K] extends new (...args: any[]) => infer C // or map of instances respectively ? UpdatedClient : never } => { return null as any} : Client> | (new (...args: any[]) => Client)>(clientDef: D) => D extends new (...args: any[]) => infer C ? UpdatedClient : { [K in keyof D]: D[K] extends new (...args: any[]) => infer C ? UpdatedClient : never; } + + D extends + | (new (...args: any[]) => Client) // accept class +>args : any[] + + | Record Client> // or map of classes +>args : any[] + +>( + clientDef: D +>clientDef : D + +): D extends new (...args: any[]) => infer C +>args : any[] + + ? UpdatedClient // return instance + : { + [K in keyof D]: D[K] extends new (...args: any[]) => infer C // or map of instances respectively +>args : any[] + + ? UpdatedClient + : never + } => { + return null as any +>null as any : any +>null : null +} diff --git a/tests/cases/compiler/declarationEmitShadowingInferNotRenamed.ts b/tests/cases/compiler/declarationEmitShadowingInferNotRenamed.ts new file mode 100644 index 00000000000..ac29eeb9d80 --- /dev/null +++ b/tests/cases/compiler/declarationEmitShadowingInferNotRenamed.ts @@ -0,0 +1,22 @@ +// @declaration: true +// Any instance type +type Client = string + +// Modified instance +type UpdatedClient = C & {foo: number} + +export const createClient = < + D extends + | (new (...args: any[]) => Client) // accept class + | Record Client> // or map of classes +>( + clientDef: D +): D extends new (...args: any[]) => infer C + ? UpdatedClient // return instance + : { + [K in keyof D]: D[K] extends new (...args: any[]) => infer C // or map of instances respectively + ? UpdatedClient + : never + } => { + return null as any +} \ No newline at end of file