TypeScript:如何推断函数返回类型的基类泛型参数并用作函数参数类型?
实现invokeFactory函数的正确类型推断方案
问题背景
我们需要实现invokeFactory函数,用于调用基于ServiceBase基类的类构造工厂函数,要求工厂函数作为无类型标注的内联函数时,其入参类型能自动从基类的泛型参数推断出来。例如调用invokeFactory((arg) => new NumberService(arg))时,arg要自动推断为number类型,同时返回的服务类型也需正确识别为NumberService。
现有尝试的问题分析
- 用
any作为工厂入参类型:虽然能正确推断服务类型TService和泛型参数TArg,但入参失去了类型检查,违背了TypeScript的类型安全初衷。 - 用条件类型指定工厂入参类型:此时TypeScript的推断顺序出现问题——它会优先尝试推断
TService,但工厂入参的类型依赖TService的推断结果,导致反向推导失败,最终TService被推断为最宽泛的ServiceBase<unknown>,TArg也变成unknown。
解决方案
调整泛型参数的约束关系,让TypeScript优先从工厂函数的返回值推断服务类型,再反向推导入参类型。核心思路是将TArg和TService的泛型约束关联起来,确保推断顺序正确。
最终实现代码
class ServiceBase<TArg = unknown> { constructor(protected arg: TArg) {} } class NumberService extends ServiceBase<number> {} const invokeFactory = <TArg, TService extends ServiceBase<TArg>>( factory: (arg: TArg) => TService ): [TService, TArg] => { // 示例中用null!占位,实际业务需传入合法的TArg类型值 const magicArg: TArg = null!; return [factory(magicArg), magicArg]; }; // 调用验证:arg自动推断为number,numberService类型为NumberService const [numberService, arg] = invokeFactory((arg) => new NumberService(arg));
方案说明
- 泛型参数
TArg作为独立的类型变量,TService被约束为ServiceBase<TArg>的子类,TypeScript会先从工厂函数的返回值(NumberService)推断出TService,再从ServiceBase的泛型参数中提取TArg,从而自动推导工厂入参的类型。 - 这种方式既保证了工厂入参的类型安全,又能让类型推断自动完成,无需手动标注工厂函数的入参类型。
内容的提问来源于stack exchange,提问作者Mahtis Michel
相关产品推荐
相关产品推荐

