如何从扩展的接口中推断泛型类型?
TypeScript泛型函数类型推断问题
问题背景
我有一个带泛型字段的接口,定义如下:
interface HasVal<T> { val: T }
我想创建一个名为get_val的函数,它可接收任何实现HasVal的实例并返回其val属性:
function get_val<T, Hv extends HasVal<T>>(hv: Hv): T { return hv.val }
但这段代码无法正常工作,因为T类型无法被正确推断:
class MyVal { val = "hello world!" } let u = get_val(new MyVal()); // u的类型为unknown :(
是否存在一种get_val的类型签名,无需调用者指定类型就能返回正确的类型?
解决方案
可以通过两种方式修复类型推断问题:
方式一:利用条件类型推断
只保留一个泛型参数,通过infer关键字从Hv的结构中自动推导val的类型:
function get_val<Hv extends HasVal<any>>(hv: Hv): Hv extends HasVal<infer T> ? T : never { return hv.val; }
方式二:索引访问类型
直接通过索引访问Hv的val属性类型,写法更简洁:
function get_val<Hv extends HasVal<any>>(hv: Hv): Hv['val'] { return hv.val; }
测试验证:
class MyVal { val = "hello world!" } let u = get_val(new MyVal()); // u的类型现在被正确推断为string ✅
原写法失效原因
原写法声明了两个独立的泛型参数T和Hv,TypeScript在推断时无法建立T与Hv['val']的强关联,只能将T fallback到unknown。而修复后的写法直接从输入参数Hv的结构中提取val的类型,消除了推断歧义。
内容的提问来源于stack exchange,提问作者kalkronline
相关产品推荐
相关产品推荐

