TypeScript中无需手动指定泛型让函数自动返回子类类型的实现问题
问题根因
你在声明fa、fb时显式指定了不带泛型参数的Foo类型,触发了泛型默认值X,直接将函数返回值类型固定为父类X,主动覆盖了TS的类型推断能力,丢失了子类的独有类型信息。
解决方案
方案1:使用satisfies操作符(TS 4.9+ 推荐)
satisfies可以验证变量符合指定类型约束,同时不会丢失变量本身的更精确类型,是该场景的最优解:
// 原有类型定义不变 class X { } class A extends X { hi() { console.log('hi') } } class B extends X { hello() { console.log('hello') } } type Foo<T extends X = X> = () => T; // 修改变量声明 const fa = (() => { return new A(); }) satisfies Foo; const fb = (() => { return new B(); }) satisfies Foo; // 调用无报错 const a = fa(); a.hi(); // 正常识别为A类型 const b = fb(); b.hello(); // 正常识别为B类型
方案2:使用泛型工具函数(兼容低版本TS)
如果你的TS版本低于4.9无法使用satisfies,可以封装一个简单的泛型工厂函数做类型校验,同时保留精确类型推断:
// 原有类型定义不变 class X { } class A extends X { hi() { console.log('hi') } } class B extends X { hello() { console.log('hello') } } type Foo<T extends X = X> = () => T; // 新增工具函数 function defineFoo<T extends X>(foo: Foo<T>) { return foo; } // 修改变量声明 const fa = defineFoo(() => { return new A(); }); const fb = defineFoo(() => { return new B(); }); // 调用效果和方案1完全一致 const a = fa(); a.hi(); const b = fb(); b.hello();
两种方案都不需要手动指定泛型参数,也不会破坏原有Foo类型的约束校验,可以完美解决返回值类型丢失的问题。
内容的提问来源于stack exchange,提问作者vladforlando
相关产品推荐
相关产品推荐

