diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ea86fc74de347..8f1b691832022 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -34776,7 +34776,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // use the resolvingSignature singleton to indicate that we deferred processing. This result will be // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and // from which we never make inferences). - if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { + if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -34789,8 +34789,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunction(signature: Signature) { - return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); + function isGenericFunctionReturningFunctionOrConstructor(signature: Signature) { + if (!signature.typeParameters) { + return false; + } + const returnType = getReturnTypeOfSignature(signature); + return isFunctionType(returnType) || isConstructorType(returnType); } /** diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols new file mode 100644 index 0000000000000..03e0bcb9f168b --- /dev/null +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols @@ -0,0 +1,72 @@ +//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// + +=== inferenceGenericNestedCallReturningConstructor.ts === +interface Action { +>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) + + new (ctx: TContext): void; +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 1, 7)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) +} + +declare class AssignAction { +>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) + + constructor(ctx: TContext); +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 5, 14)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) +} + +declare function assign( +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) + + assigner: (ctx: TContext) => void +>assigner : Symbol(assigner, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 34)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 9, 13)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) + +): { + new (ctx: TContext): AssignAction; +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 11, 7)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) +>AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) +} + +declare function createMachine(config: { +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) +>config : Symbol(config, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 41)) + + context: TContext; +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 50)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) + + entry: Action; +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 20)) +>Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) + +}): void; + +createMachine({ +>createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) + + context: { count: 0 }, +>context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 19, 15)) +>count : Symbol(count, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 12)) + + entry: assign((ctx) => { +>entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 24)) +>assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) + + ctx // { count: number } +>ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) + + }), +}); + diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types new file mode 100644 index 0000000000000..ce6d09b4d3281 --- /dev/null +++ b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types @@ -0,0 +1,63 @@ +//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// + +=== inferenceGenericNestedCallReturningConstructor.ts === +interface Action { + new (ctx: TContext): void; +>ctx : TContext +} + +declare class AssignAction { +>AssignAction : AssignAction + + constructor(ctx: TContext); +>ctx : TContext +} + +declare function assign( +>assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction + + assigner: (ctx: TContext) => void +>assigner : (ctx: TContext) => void +>ctx : TContext + +): { + new (ctx: TContext): AssignAction; +>ctx : TContext +} + +declare function createMachine(config: { +>createMachine : (config: { context: TContext; entry: Action;}) => void +>config : { context: TContext; entry: Action; } + + context: TContext; +>context : TContext + + entry: Action; +>entry : Action + +}): void; + +createMachine({ +>createMachine({ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),}) : void +>createMachine : (config: { context: TContext; entry: Action; }) => void +>{ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),} : { context: { count: number; }; entry: new (ctx: { count: number; }) => AssignAction<{ count: number; }>; } + + context: { count: 0 }, +>context : { count: number; } +>{ count: 0 } : { count: number; } +>count : number +>0 : 0 + + entry: assign((ctx) => { +>entry : new (ctx: { count: number; }) => AssignAction<{ count: number; }> +>assign((ctx) => { ctx // { count: number } }) : new (ctx: { count: number; }) => AssignAction<{ count: number; }> +>assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction +>(ctx) => { ctx // { count: number } } : (ctx: { count: number; }) => void +>ctx : { count: number; } + + ctx // { count: number } +>ctx : { count: number; } + + }), +}); + diff --git a/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts new file mode 100644 index 0000000000000..8c1ea32096284 --- /dev/null +++ b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts @@ -0,0 +1,28 @@ +// @strict: true +// @noEmit: true + +interface Action { + new (ctx: TContext): void; +} + +declare class AssignAction { + constructor(ctx: TContext); +} + +declare function assign( + assigner: (ctx: TContext) => void +): { + new (ctx: TContext): AssignAction; +} + +declare function createMachine(config: { + context: TContext; + entry: Action; +}): void; + +createMachine({ + context: { count: 0 }, + entry: assign((ctx) => { + ctx // { count: number } + }), +});