如何声明可传递自身泛型到返回实例的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
相关产品推荐
相关产品推荐

