diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac77a64bb64..46cb8bb4937 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15705,9 +15705,10 @@ namespace ts { // // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. + const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; let excludeArgument: boolean[]; let excludeCount = 0; - if (!isDecorator) { + if (!isDecorator && !isSingleNonGenericCandidate) { // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { @@ -15860,6 +15861,19 @@ namespace ts { function chooseOverload(candidates: Signature[], relation: Map, signatureHelpTrailingComma = false) { candidateForArgumentError = undefined; candidateForTypeArgumentError = undefined; + + if (isSingleNonGenericCandidate) { + const candidate = candidates[0]; + if (!hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { + return undefined; + } + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { + candidateForArgumentError = candidate; + return undefined; + } + return candidate; + } + for (let candidateIndex = 0; candidateIndex < candidates.length; candidateIndex++) { const originalCandidate = candidates[candidateIndex]; if (!hasCorrectArity(node, args, originalCandidate, signatureHelpTrailingComma)) { @@ -15907,7 +15921,6 @@ namespace ts { return undefined; } - } function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number { diff --git a/tests/baselines/reference/contextualTypingFunctionReturningFunction.js b/tests/baselines/reference/contextualTypingFunctionReturningFunction.js new file mode 100644 index 00000000000..31f89bdefd8 --- /dev/null +++ b/tests/baselines/reference/contextualTypingFunctionReturningFunction.js @@ -0,0 +1,19 @@ +//// [contextualTypingFunctionReturningFunction.ts] +interface I { + a(s: string): void; + b(): (n: number) => void; +} + +declare function f(i: I): void; + +f({ + a: s => {}, + b: () => n => {}, +}); + + +//// [contextualTypingFunctionReturningFunction.js] +f({ + a: function (s) { }, + b: function () { return function (n) { }; } +}); diff --git a/tests/baselines/reference/contextualTypingFunctionReturningFunction.symbols b/tests/baselines/reference/contextualTypingFunctionReturningFunction.symbols new file mode 100644 index 00000000000..509c7129745 --- /dev/null +++ b/tests/baselines/reference/contextualTypingFunctionReturningFunction.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/contextualTypingFunctionReturningFunction.ts === +interface I { +>I : Symbol(I, Decl(contextualTypingFunctionReturningFunction.ts, 0, 0)) + + a(s: string): void; +>a : Symbol(I.a, Decl(contextualTypingFunctionReturningFunction.ts, 0, 13)) +>s : Symbol(s, Decl(contextualTypingFunctionReturningFunction.ts, 1, 3)) + + b(): (n: number) => void; +>b : Symbol(I.b, Decl(contextualTypingFunctionReturningFunction.ts, 1, 20)) +>n : Symbol(n, Decl(contextualTypingFunctionReturningFunction.ts, 2, 7)) +} + +declare function f(i: I): void; +>f : Symbol(f, Decl(contextualTypingFunctionReturningFunction.ts, 3, 1)) +>i : Symbol(i, Decl(contextualTypingFunctionReturningFunction.ts, 5, 19)) +>I : Symbol(I, Decl(contextualTypingFunctionReturningFunction.ts, 0, 0)) + +f({ +>f : Symbol(f, Decl(contextualTypingFunctionReturningFunction.ts, 3, 1)) + + a: s => {}, +>a : Symbol(a, Decl(contextualTypingFunctionReturningFunction.ts, 7, 3)) +>s : Symbol(s, Decl(contextualTypingFunctionReturningFunction.ts, 8, 3)) + + b: () => n => {}, +>b : Symbol(b, Decl(contextualTypingFunctionReturningFunction.ts, 8, 12)) +>n : Symbol(n, Decl(contextualTypingFunctionReturningFunction.ts, 9, 9)) + +}); + diff --git a/tests/baselines/reference/contextualTypingFunctionReturningFunction.types b/tests/baselines/reference/contextualTypingFunctionReturningFunction.types new file mode 100644 index 00000000000..8185819acf6 --- /dev/null +++ b/tests/baselines/reference/contextualTypingFunctionReturningFunction.types @@ -0,0 +1,36 @@ +=== tests/cases/compiler/contextualTypingFunctionReturningFunction.ts === +interface I { +>I : I + + a(s: string): void; +>a : (s: string) => void +>s : string + + b(): (n: number) => void; +>b : () => (n: number) => void +>n : number +} + +declare function f(i: I): void; +>f : (i: I) => void +>i : I +>I : I + +f({ +>f({ a: s => {}, b: () => n => {},}) : void +>f : (i: I) => void +>{ a: s => {}, b: () => n => {},} : { a: (s: string) => void; b: () => (n: number) => void; } + + a: s => {}, +>a : (s: string) => void +>s => {} : (s: string) => void +>s : string + + b: () => n => {}, +>b : () => (n: number) => void +>() => n => {} : () => (n: number) => void +>n => {} : (n: number) => void +>n : number + +}); + diff --git a/tests/baselines/reference/invalidThisEmitInContextualObjectLiteral.types b/tests/baselines/reference/invalidThisEmitInContextualObjectLiteral.types index 290b0a78eb2..8cb32eb84bd 100644 --- a/tests/baselines/reference/invalidThisEmitInContextualObjectLiteral.types +++ b/tests/baselines/reference/invalidThisEmitInContextualObjectLiteral.types @@ -25,7 +25,7 @@ class TestController { >this.m : (def: IDef) => void >this : this >m : (def: IDef) => void ->{ p1: e => { }, p2: () => { return vvvvvvvvv => this; }, } : { p1: (e: string) => void; p2: () => {}; } +>{ p1: e => { }, p2: () => { return vvvvvvvvv => this; }, } : { p1: (e: string) => void; p2: () => (vvvvvvvvv: number) => this; } p1: e => { }, >p1 : (e: string) => void @@ -33,8 +33,8 @@ class TestController { >e : string p2: () => { return vvvvvvvvv => this; }, ->p2 : () => {} ->() => { return vvvvvvvvv => this; } : () => {} +>p2 : () => (vvvvvvvvv: number) => this +>() => { return vvvvvvvvv => this; } : () => (vvvvvvvvv: number) => this >vvvvvvvvv => this : (vvvvvvvvv: number) => this >vvvvvvvvv : number >this : this diff --git a/tests/cases/compiler/contextualTypingFunctionReturningFunction.ts b/tests/cases/compiler/contextualTypingFunctionReturningFunction.ts new file mode 100644 index 00000000000..2b371937f5c --- /dev/null +++ b/tests/cases/compiler/contextualTypingFunctionReturningFunction.ts @@ -0,0 +1,11 @@ +interface I { + a(s: string): void; + b(): (n: number) => void; +} + +declare function f(i: I): void; + +f({ + a: s => {}, + b: () => n => {}, +});