Skip to content

Commit 7ab5d83

Browse files
authored
Merge pull request #32594 from microsoft/fix32416
Instantiate contextual type for object literal methods
2 parents 3d09010 + 4a17581 commit 7ab5d83

File tree

5 files changed

+82
-7
lines changed

5 files changed

+82
-7
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19099,10 +19099,13 @@ namespace ts {
1909919099

1910019100
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
1910119101
// be "pushed" onto a node using the contextualType property.
19102-
function getApparentTypeOfContextualType(node: Expression, contextFlags?: ContextFlags): Type | undefined {
19103-
const contextualType = instantiateContextualType(getContextualType(node, contextFlags), node, contextFlags);
19104-
if (contextualType) {
19105-
const apparentType = mapType(contextualType, getApparentType, /*noReductions*/ true);
19102+
function getApparentTypeOfContextualType(node: Expression | MethodDeclaration, contextFlags?: ContextFlags): Type | undefined {
19103+
const contextualType = isObjectLiteralMethod(node) ?
19104+
getContextualTypeForObjectLiteralMethod(node, contextFlags) :
19105+
getContextualType(node, contextFlags);
19106+
const instantiatedType = instantiateContextualType(contextualType, node, contextFlags);
19107+
if (instantiatedType) {
19108+
const apparentType = mapType(instantiatedType, getApparentType, /*noReductions*/ true);
1910619109
if (apparentType.flags & TypeFlags.Union) {
1910719110
if (isObjectLiteralExpression(node)) {
1910819111
return discriminateContextualTypeByObjectMembers(node, apparentType as UnionType);
@@ -19426,9 +19429,7 @@ namespace ts {
1942619429
if (typeTagSignature) {
1942719430
return typeTagSignature;
1942819431
}
19429-
const type = isObjectLiteralMethod(node) ?
19430-
getContextualTypeForObjectLiteralMethod(node, ContextFlags.Signature) :
19431-
getApparentTypeOfContextualType(node, ContextFlags.Signature);
19432+
const type = getApparentTypeOfContextualType(node, ContextFlags.Signature);
1943219433
if (!type) {
1943319434
return undefined;
1943419435
}

tests/baselines/reference/instantiateContextualTypes.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ class Interesting {
172172
declare function invoke<T>(f: () => T): T;
173173

174174
let xx: 0 | 1 | 2 = invoke(() => 1);
175+
176+
// Repro from #32416
177+
178+
declare function assignPartial<T>(target: T, partial: Partial<T>): T;
179+
180+
let obj = {
181+
foo(bar: string) {}
182+
}
183+
184+
assignPartial(obj, { foo(...args) {} }); // args has type [string]
175185

176186

177187
//// [instantiateContextualTypes.js]
@@ -222,3 +232,7 @@ class Interesting {
222232
}
223233
}
224234
let xx = invoke(() => 1);
235+
let obj = {
236+
foo(bar) { }
237+
};
238+
assignPartial(obj, { foo(...args) { } }); // args has type [string]

tests/baselines/reference/instantiateContextualTypes.symbols

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,3 +481,29 @@ let xx: 0 | 1 | 2 = invoke(() => 1);
481481
>xx : Symbol(xx, Decl(instantiateContextualTypes.ts, 172, 3))
482482
>invoke : Symbol(invoke, Decl(instantiateContextualTypes.ts, 166, 1))
483483

484+
// Repro from #32416
485+
486+
declare function assignPartial<T>(target: T, partial: Partial<T>): T;
487+
>assignPartial : Symbol(assignPartial, Decl(instantiateContextualTypes.ts, 172, 36))
488+
>T : Symbol(T, Decl(instantiateContextualTypes.ts, 176, 31))
489+
>target : Symbol(target, Decl(instantiateContextualTypes.ts, 176, 34))
490+
>T : Symbol(T, Decl(instantiateContextualTypes.ts, 176, 31))
491+
>partial : Symbol(partial, Decl(instantiateContextualTypes.ts, 176, 44))
492+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
493+
>T : Symbol(T, Decl(instantiateContextualTypes.ts, 176, 31))
494+
>T : Symbol(T, Decl(instantiateContextualTypes.ts, 176, 31))
495+
496+
let obj = {
497+
>obj : Symbol(obj, Decl(instantiateContextualTypes.ts, 178, 3))
498+
499+
foo(bar: string) {}
500+
>foo : Symbol(foo, Decl(instantiateContextualTypes.ts, 178, 11))
501+
>bar : Symbol(bar, Decl(instantiateContextualTypes.ts, 179, 6))
502+
}
503+
504+
assignPartial(obj, { foo(...args) {} }); // args has type [string]
505+
>assignPartial : Symbol(assignPartial, Decl(instantiateContextualTypes.ts, 172, 36))
506+
>obj : Symbol(obj, Decl(instantiateContextualTypes.ts, 178, 3))
507+
>foo : Symbol(foo, Decl(instantiateContextualTypes.ts, 182, 20))
508+
>args : Symbol(args, Decl(instantiateContextualTypes.ts, 182, 25))
509+

tests/baselines/reference/instantiateContextualTypes.types

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,27 @@ let xx: 0 | 1 | 2 = invoke(() => 1);
422422
>() => 1 : () => 1
423423
>1 : 1
424424

425+
// Repro from #32416
426+
427+
declare function assignPartial<T>(target: T, partial: Partial<T>): T;
428+
>assignPartial : <T>(target: T, partial: Partial<T>) => T
429+
>target : T
430+
>partial : Partial<T>
431+
432+
let obj = {
433+
>obj : { foo(bar: string): void; }
434+
>{ foo(bar: string) {}} : { foo(bar: string): void; }
435+
436+
foo(bar: string) {}
437+
>foo : (bar: string) => void
438+
>bar : string
439+
}
440+
441+
assignPartial(obj, { foo(...args) {} }); // args has type [string]
442+
>assignPartial(obj, { foo(...args) {} }) : { foo(bar: string): void; }
443+
>assignPartial : <T>(target: T, partial: Partial<T>) => T
444+
>obj : { foo(bar: string): void; }
445+
>{ foo(...args) {} } : { foo(bar: string): void; }
446+
>foo : (bar: string) => void
447+
>args : [string]
448+

tests/cases/compiler/instantiateContextualTypes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,13 @@ class Interesting {
174174
declare function invoke<T>(f: () => T): T;
175175

176176
let xx: 0 | 1 | 2 = invoke(() => 1);
177+
178+
// Repro from #32416
179+
180+
declare function assignPartial<T>(target: T, partial: Partial<T>): T;
181+
182+
let obj = {
183+
foo(bar: string) {}
184+
}
185+
186+
assignPartial(obj, { foo(...args) {} }); // args has type [string]

0 commit comments

Comments
 (0)