TypeScript中如何约束泛型对象指定key对应的属性值类型?
TypeScript 泛型字段类型约束实现
核心思路
通过约束泛型T的指定键K对应的属性值类型为目标类型(此处为string),即可在编译阶段拦截不符合要求的入参。
实现代码
固定约束为string的版本
function foo<T extends Record<K, string>, K extends keyof T>(obj: T, key: K) { console.log(obj[key]) }
测试效果
- 合法调用无报错:
foo({ fox: 'Mulder' }, 'fox') // 正常运行,输出Mulder
- 非法调用触发编译错误:
foo({ fox: 22 }, 'fox') // TS报错:类型“{ fox: number; }”的参数不能赋给类型“Record<"fox", string>”的参数。属性“fox”的类型不兼容。不能将类型“number”分配给类型“string”。
可自定义目标类型的通用版本
如果需要灵活切换约束的目标类型,可以把目标类型抽为泛型参数:
// X为你要约束的目标类型,使用时显式指定即可 function foo<X, T extends Record<K, X>, K extends keyof T>(obj: T, key: K) { console.log(obj[key]) } // 约束为string类型时的调用示例 foo<string>({ fox: 'Mulder' }, 'fox') // 正常 foo<string>({ fox: 22 }, 'fox') // 触发错误
原理解释
Record<K, T>是TypeScript内置工具类型,本质是语法糖,等价于{ [P in K]: T },表示对象的K键对应的值必须为T类型。- 泛型约束
T extends Record<K, string>强制要求传入的obj对象,在指定key上的属性值必须是string类型,不符合该约束的入参会直接在编译阶段抛出错误,不需要运行时判断。
内容的提问来源于stack exchange,提问作者Sasgorilla
相关产品推荐
相关产品推荐

