TypeScript中getDeepValue泛型用extends与不用的差异及报错问题
关于TypeScript getDeepValue函数的类型问题解析
两种写法的核心差异
错误写法
export const getDeepValue = <T, >(obj: T, firstKey: keyof T, secondKey: keyof T[keyof T]) => { return obj[firstKey][secondKey]; }; const obj = { foo: { a: true, b: 2, }, bar: { c: "12", d: 18, }, }; const value = getDeepValue(obj, "foo", "a"); // 报错:secondKey类型为never
正确写法
export const getDeepValue = <T, TFK extends keyof T, TSK extends keyof T[TFK]>(obj: T, firstKey: TFK, secondKey: TSK) => { return obj[firstKey][secondKey]; }; const obj = { foo: { a: true, b: 2, }, bar: { c: "12", d: 18, }, }; const value = getDeepValue(obj, "foo", "a"); // 类型正常推导
两者的差异在于泛型的绑定逻辑:
- 错误写法只声明了泛型
T,secondKey的类型是所有子对象key的交集,而非对应firstKey的子对象key。 - 正确写法额外声明了
TFK(绑定传入的firstKey的具体类型)和TSK(绑定TFK对应子对象的key类型),让secondKey的类型和firstKey强关联,实现了类型的精准推导。
为什么不能用keyof T[keyof T]作为secondKey的类型?
T[keyof T]表示的是T中所有属性值的联合类型,在你的例子里就是{a: true, b:2} | {c:"12", d:18}。
而keyof作用于联合类型时,只会返回所有类型共有的key(也就是交集)。你的例子里两个子对象的keya/b和c/d没有任何交集,所以keyof ({a: true, b:2} | {c:"12", d:18})的结果就是never——这就是为什么代码会报错secondKey为never类型。
换个场景,如果两个子对象有共同key,比如foo和bar都有x属性,那keyof T[keyof T]会是x,但这依然无法实现firstKey和secondKey的关联:比如你传入firstKey为foo,secondKey却能传x之外的a,这显然不符合逻辑。
内容的提问来源于stack exchange,提问作者Jason Ch.
相关产品推荐
相关产品推荐

