如何实现将类型属性名首字母大写的TypeScript泛型?
TypeScript 属性名首字母大写泛型实现方案
该需求完全可以实现,你之前两种方案失效的核心原因是没有在映射时建立新键和原键的直接绑定关系,正确实现需要用到TypeScript 4.1+支持的映射类型键重映射(as 语法)。
正确实现代码
type CapitalizedProps<T> = { [K in keyof T as Capitalize<K & string>]: T[K] }
效果验证
用你给出的示例类型测试,推导结果完全符合预期:
type Example = { id: number name: string AnotherProperty: boolean } type CapitalizedExample = CapitalizedProps<Example> // 推导结果等价于: // { // Id: number, // Name: string, // AnotherProperty: boolean // } // 合法赋值可正常通过校验 const validCase: CapitalizedProps<Example> = { Id: 1, Name: 'test', AnotherProperty: true } // 非法赋值会被正确拦截 const errorCase1: CapitalizedProps<Example> = { Id: 1, name: 'test', // 类型错误:"name"不属于目标类型的已知属性 AnotherProperty: true } const errorCase2: CapitalizedProps<Example> = { Id: 1, Name: 1337, // 类型错误:number不能赋值给string类型 AnotherProperty: true }
原有方案问题说明
- 第一种方案问题:先把所有原键做首字母大写得到新键集合,再通过
Uncapitalize<K>反查原键取值。但Uncapitalize是强制将首字母转小写的操作,原本就首字母大写的键(比如AnotherProperty)会被错误转成anotherProperty,原类型中不存在这个键,对应值类型就会被推为never;同时反查逻辑没有绑定键值一一对应关系,会漏过未大写的非法属性名。 - 第二种方案问题:直接将值类型设为
T[keyof T](原类型所有属性值的联合类型),完全丢失了键和值的对应关系,自然无法校验单个属性的赋值类型。
实现原理
键重映射语法[K in keyof T as 转换后的键名]会直接遍历原类型的每一个属性键K,在当前遍历上下文中将K转换为新键名,值类型直接取原类型对应K的类型T[K],全程不需要反向推导键名,从根本上避免了反查带来的类型不匹配问题。
基于这个写法,搭配TypeScript内置的Lowercase/Uppercase/Uncapitalize字符串工具类型,还可以实现驼峰/蛇形/短横线命名等各种键名格式转换需求。
内容的提问来源于stack exchange,提问作者Wilco
相关产品推荐
相关产品推荐

