如何在TypeScript中基于两种类型推断函数参数的类型?
如何正确推断TypeScript函数参数的关联类型?
我定义了以下两种类型:
type one = { test1: string; test2: string; test3: string; } type two = { test3: string; test4: string; }
我编写了一个函数,希望接受上述两种类型中的任意一个键作为参数:
function setId( key: keyof one | keyof two, value: | one[typeof key] // 此处报错 - 第10行 | two[typeof key] ) { setField(value); }
第10行出现两个错误:
Property 'test3' does not exist on type 'one'
Property 'test4' does not exist on type 'one'
由于setId函数的key参数可以是one或two类型的任意键,请问如何正确推断value参数的类型?
问题原因
原写法的核心问题是没有建立key与对应类型的关联:当key是keyof one | keyof two的联合类型时,typeof key会包含所有四个键(test1/test2/test3/test4),TypeScript会尝试对每个键去匹配one和two的属性,但one不存在test4,two不存在test1/test2,因此触发类型错误。
解决方案
可以通过泛型约束或条件类型来明确key与value的类型关联,以下是几种可行写法:
写法1:函数重载
通过重载定义两种参数组合,让TypeScript明确不同key对应的value类型:
// 重载签名:分别处理one和two的键值对 function setId<K extends keyof one>(key: K, value: one[K]): void; function setId<K extends keyof two>(key: K, value: two[K]): void; // 实现签名 function setId(key: keyof one | keyof two, value: string) { setField(value); }
写法2:条件类型关联
利用条件类型判断key所属的类型,动态推导对应的value类型:
function setId<K extends keyof (one | two)>( key: K, value: K extends keyof one ? one[K] : two[K] ) { setField(value); }
写法3:泛型约束整体类型
通过泛型限定参数属于one或two,直接关联key和对应的value类型:
function setId<T extends one | two>(key: keyof T, value: T[keyof T]) { setField(value); } // 调用示例(可手动指定泛型,或让TypeScript自动推断) setId<one>('test1', 'abc'); setId<two>('test4', 'def');
写法4:联合键值对类型
预先定义合法的键值对联合类型,直接作为函数参数:
type ValidKeyValue = | { key: keyof one; value: one[keyof one] } | { key: keyof two; value: two[keyof two] }; function setId({ key, value }: ValidKeyValue) { setField(value); }
以上写法都能确保key和value的类型匹配,避免原有的类型错误。
内容的提问来源于stack exchange,提问作者TestYellerOP
相关产品推荐
相关产品推荐

