You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何声明可传递自身泛型到返回实例的TypeScript工厂接口

解决方案

核心思路是通过泛型推导提取传入的Foo派生类的完整类型,再将工厂的泛型T注入到类的Foo基类泛型位置,同时保留派生类的独有属性定义。

正确接口定义

// 泛型工具:将Foo派生类R的泛型参数替换为T
type ReplaceFooGeneric<T, R extends Foo<any>> = 
  R extends Foo<infer _> ? Omit<R, keyof Foo> & Foo<T> : never;

interface IFactory<T> {
  create<C extends new (...args: any[]) => Foo<any>>(ctor: C): ReplaceFooGeneric<T, InstanceType<C>>;
}

如果你使用TypeScript 4.9及以上版本,可通过infer extends语法简化,无需单独抽取工具类型:

interface IFactory<T> {
  create<C extends new (...args: any[]) => Foo<any>>(ctor: C): 
    C extends new (...args: any[]) => infer R extends Foo<any>
      ? Omit<R, keyof Foo> & Foo<T>
      : never;
}

原写法问题说明

  • create1的返回值约束为R extends Foo<T>,TypeScript类型推导时会优先将R向上兼容到Foo<T>,擦除了派生类(如Moo)的独有属性定义,所以返回类型被推导为Foo。
  • create2只约束了构造函数返回Foo<T>,但没有将构造函数本身的泛型参数和工厂的T绑定,TypeScript无法自动关联派生类的泛型参数和工厂泛型,所以实例泛型被推导为unknown。

效果验证

const factory = {} as IFactory<string>;
const mooInstance = factory.create(Moo);

mooInstance.test // 类型为string,符合预期
mooInstance.moo // 类型为string,返回类型为Moo<string>,符合预期

内容的提问来源于stack exchange,提问作者vladforlando

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 10:27:01