TypeScript:能否补全单键对象函数类型以返回指定键值类型?
TypeScript动态键名函数的精确类型定义方案
嘿,你这个问题其实很典型——很多人刚接触TypeScript泛型映射的时候都会踩这个小坑!你尝试的方向没错,只是写法上差了一点点细节,我来给你捋清楚:
正确的实现方案
你想要的精确返回类型是完全可以实现的,关键是用映射类型替代普通的索引签名写法。这里是正确的代码:
const fn = <K extends string | number | symbol, T>(name: K, value: T): { [key in K]: T } => ({ [name]: value });
测试一下调用效果:
const someT = "world"; const result = fn("hello", someT); // 此时result的类型会被精确推断为 { hello: string },完全符合你的预期
为什么你之前的写法没生效?
你之前写的{ [k: K]: T }是普通索引签名的写法,它的语义是「这个对象的所有键都属于K类型」,但TypeScript不会把它解析为「只有一个键是K的具体字面量值」。而用[key in K]的映射类型,会直接把泛型K的具体字面量(比如传入的"hello")映射成对象的唯一键,从而得到精确的返回类型。
如果你的TS版本比较新(3.4+),甚至不用额外断言,TypeScript会自动把传入的字符串字面量推断为K的具体类型。如果怕类型被拓宽,也可以给返回值加个as const断言更保险:
const fn = <K extends string | number | symbol, T>(name: K, value: T): { [key in K]: T } => ({ [name]: value } as const);
更简洁的替代方案
TypeScript内置了Record工具类型,它本质上就是封装好的映射类型,用它可以让代码更简洁:
const fn = <K extends string | number | symbol, T>(name: K, value: T): Record<K, T> => ({ [name]: value });
Record<K, T>和{ [key in K]: T }是完全等价的,同样能实现精确的返回类型推断。
内容的提问来源于stack exchange,提问作者Gerrit Begher
相关产品推荐
相关产品推荐

