如何让TypeScript的readProperty函数根据参数推导返回值类型?
问题需求
当部分对象的类型定义存在异常时,开发者明确知道属性的预期类型,但编译器无法识别。需要实现一个readProperty函数,能够提取符合预期类型的属性值,若实际类型与预期不符则抛出错误。同时要求编译器能根据调用时传入的typeName参数,自动推导函数的返回值类型——比如调用readProperty(someObj, "x", "number")时,编译器能识别返回值为number类型;调用readProperty(someObj, "y", "string")时,识别返回值为string类型。
原代码示例:
function readProperty<T>(obj: T, key: keyof T, typeName: "string" | "number"): string | number { const value = obj[key] if (typeof value != typeName) { throw new Error(`Property ${key.toString()} must be a ${typeName}`) } return value } const someObj = { x: "123", y: 123, } const x = readProperty(someObj, "x", "number") // 期望编译器识别x为number类型 const y = readProperty(someObj, "y", "string") // 期望编译器识别y为string类型
解决方案
可以通过泛型类型映射实现编译器的类型推导,将typeName参数与返回值类型关联起来:
// 建立类型名字符串到实际TypeScript类型的映射 type TypeNameToType = { string: string; number: number; }; // 新增泛型K,约束为TypeNameToType的键类型 function readProperty<T, K extends keyof TypeNameToType>( obj: T, key: keyof T, typeName: K ): TypeNameToType[K] { const value = obj[key]; if (typeof value !== typeName) { throw new Error(`Property ${String(key)} must be a ${typeName}`); } // 类型断言,告诉编译器此时value的类型符合TypeNameToType[K] return value as TypeNameToType[K]; } const someObj = { x: "123", y: 123, }; // 编译器自动推导x为number类型(运行时会抛错,因为someObj.x实际是string) const x = readProperty(someObj, "x", "number"); // 编译器自动推导y为string类型(运行时会抛错,因为someObj.y实际是number) const y = readProperty(someObj, "y", "string");
关键说明
- 类型映射
TypeNameToType:将"string"、"number"这些字符串字面量类型,映射到对应的TypeScript基础类型,让编译器能建立参数与返回值的类型关联。 - 泛型
K:约束typeName只能是TypeNameToType的键,确保传入的类型名字符串是合法的,同时让编译器能根据传入的K值,推导返回值为TypeNameToType[K]。 - 类型断言:由于TypeScript的typeof操作符在类型层面无法直接关联到
K,所以需要用as TypeNameToType[K]告诉编译器,经过typeof检查后,value的类型符合预期。
这样既满足了运行时的类型校验(类型不符抛错),又实现了编译时的类型推导,让编译器能准确识别返回值类型。
内容的提问来源于stack exchange,提问作者birgersp
相关产品推荐
相关产品推荐

