Skip to content

Commit 8d1fa44

Browse files
Andaristsandersn
andauthored
Defer processing of nested generic calls that return constructor types (#54813)
Co-authored-by: Nathan Shively-Sanders <[email protected]>
1 parent eb2046d commit 8d1fa44

4 files changed

+170
-3
lines changed

src/compiler/checker.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -34776,7 +34776,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3477634776
// use the resolvingSignature singleton to indicate that we deferred processing. This result will be
3477734777
// propagated out and eventually turned into silentNeverType (a type that is assignable to anything and
3477834778
// from which we never make inferences).
34779-
if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) {
34779+
if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) {
3478034780
skippedGenericFunction(node, checkMode);
3478134781
return resolvingSignature;
3478234782
}
@@ -34789,8 +34789,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3478934789
return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags);
3479034790
}
3479134791

34792-
function isGenericFunctionReturningFunction(signature: Signature) {
34793-
return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature)));
34792+
function isGenericFunctionReturningFunctionOrConstructor(signature: Signature) {
34793+
if (!signature.typeParameters) {
34794+
return false;
34795+
}
34796+
const returnType = getReturnTypeOfSignature(signature);
34797+
return isFunctionType(returnType) || isConstructorType(returnType);
3479434798
}
3479534799

3479634800
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] ////
2+
3+
=== inferenceGenericNestedCallReturningConstructor.ts ===
4+
interface Action<TContext> {
5+
>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0))
6+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17))
7+
8+
new (ctx: TContext): void;
9+
>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 1, 7))
10+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17))
11+
}
12+
13+
declare class AssignAction<TContext> {
14+
>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1))
15+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27))
16+
17+
constructor(ctx: TContext);
18+
>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 5, 14))
19+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27))
20+
}
21+
22+
declare function assign<TContext>(
23+
>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1))
24+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24))
25+
26+
assigner: (ctx: TContext) => void
27+
>assigner : Symbol(assigner, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 34))
28+
>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 9, 13))
29+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24))
30+
31+
): {
32+
new (ctx: TContext): AssignAction<TContext>;
33+
>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 11, 7))
34+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24))
35+
>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1))
36+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24))
37+
}
38+
39+
declare function createMachine<TContext>(config: {
40+
>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1))
41+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31))
42+
>config : Symbol(config, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 41))
43+
44+
context: TContext;
45+
>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 50))
46+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31))
47+
48+
entry: Action<TContext>;
49+
>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 20))
50+
>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0))
51+
>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31))
52+
53+
}): void;
54+
55+
createMachine({
56+
>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1))
57+
58+
context: { count: 0 },
59+
>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 19, 15))
60+
>count : Symbol(count, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 12))
61+
62+
entry: assign((ctx) => {
63+
>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 24))
64+
>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1))
65+
>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17))
66+
67+
ctx // { count: number }
68+
>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17))
69+
70+
}),
71+
});
72+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] ////
2+
3+
=== inferenceGenericNestedCallReturningConstructor.ts ===
4+
interface Action<TContext> {
5+
new (ctx: TContext): void;
6+
>ctx : TContext
7+
}
8+
9+
declare class AssignAction<TContext> {
10+
>AssignAction : AssignAction<TContext>
11+
12+
constructor(ctx: TContext);
13+
>ctx : TContext
14+
}
15+
16+
declare function assign<TContext>(
17+
>assign : <TContext>(assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction<TContext>
18+
19+
assigner: (ctx: TContext) => void
20+
>assigner : (ctx: TContext) => void
21+
>ctx : TContext
22+
23+
): {
24+
new (ctx: TContext): AssignAction<TContext>;
25+
>ctx : TContext
26+
}
27+
28+
declare function createMachine<TContext>(config: {
29+
>createMachine : <TContext>(config: { context: TContext; entry: Action<TContext>;}) => void
30+
>config : { context: TContext; entry: Action<TContext>; }
31+
32+
context: TContext;
33+
>context : TContext
34+
35+
entry: Action<TContext>;
36+
>entry : Action<TContext>
37+
38+
}): void;
39+
40+
createMachine({
41+
>createMachine({ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),}) : void
42+
>createMachine : <TContext>(config: { context: TContext; entry: Action<TContext>; }) => void
43+
>{ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),} : { context: { count: number; }; entry: new (ctx: { count: number; }) => AssignAction<{ count: number; }>; }
44+
45+
context: { count: 0 },
46+
>context : { count: number; }
47+
>{ count: 0 } : { count: number; }
48+
>count : number
49+
>0 : 0
50+
51+
entry: assign((ctx) => {
52+
>entry : new (ctx: { count: number; }) => AssignAction<{ count: number; }>
53+
>assign((ctx) => { ctx // { count: number } }) : new (ctx: { count: number; }) => AssignAction<{ count: number; }>
54+
>assign : <TContext>(assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction<TContext>
55+
>(ctx) => { ctx // { count: number } } : (ctx: { count: number; }) => void
56+
>ctx : { count: number; }
57+
58+
ctx // { count: number }
59+
>ctx : { count: number; }
60+
61+
}),
62+
});
63+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
interface Action<TContext> {
5+
new (ctx: TContext): void;
6+
}
7+
8+
declare class AssignAction<TContext> {
9+
constructor(ctx: TContext);
10+
}
11+
12+
declare function assign<TContext>(
13+
assigner: (ctx: TContext) => void
14+
): {
15+
new (ctx: TContext): AssignAction<TContext>;
16+
}
17+
18+
declare function createMachine<TContext>(config: {
19+
context: TContext;
20+
entry: Action<TContext>;
21+
}): void;
22+
23+
createMachine({
24+
context: { count: 0 },
25+
entry: assign((ctx) => {
26+
ctx // { count: number }
27+
}),
28+
});

0 commit comments

Comments
 (0)