TypeScript中如何基于已有类型实现驼峰与蛇形键转换?
TypeScript类型自动转换:camelCase与snake_case互转
需求背景
需要对接两个格式不同的系统,它们的JSON键分别采用camelCase(驼峰式)和snake_case(蛇形式)格式。希望在TypeScript中仅定义一种类型,就能自动推导生成另一种类型。
示例如下:
// [camelCase系统] 定义的类型 type consumerSchemaCamelCase = { categoryName: string, // 👈 camelCase productId: number, isAvailable: boolean } // [snake_case系统] 需要从上述类型自动推导的类型 type consumerSchemaSnakeCase = { category_name: string, // 👈 snake_case product_id: number, is_available: boolean }
需要实现类似JavaScript中inputKey.replace(/[A-Z]/g, x => _${x.toLowerCase()})的字符串转换逻辑,但要在TypeScript类型层面完成。
实现方案
利用TypeScript的递归字符串字面量类型和映射类型,可以实现键名在两种格式之间的双向转换。
1. CamelCase转SnakeCase
先实现单个键名的字符转换逻辑,再通过映射类型遍历整个对象的键:
// 核心:递归处理字符串,将大写字母转为"_小写字母" type CamelToSnakeKey<S extends string> = S extends `${infer Prefix}${infer Capital}${infer Suffix}` ? Capital extends Uppercase<Capital> ? `${Lowercase<Prefix>}_${Lowercase<Capital>}${CamelToSnakeKey<Suffix>}` : `${Prefix}${Capital}${CamelToSnakeKey<Suffix>}` : Lowercase<S>; // 遍历对象所有键,完成camelCase到snake_case的转换,值类型保持不变 type CamelToSnake<BaseType> = { [Key in keyof BaseType as CamelToSnakeKey<string & Key>]: BaseType[Key] };
使用示例
type consumerSchemaCamelCase = { categoryName: string, productId: number, isAvailable: boolean }; // 自动推导snake_case类型 type consumerSchemaSnakeCase = CamelToSnake<consumerSchemaCamelCase>; // 等价于: // type consumerSchemaSnakeCase = { // category_name: string; // product_id: number; // is_available: boolean; // }
2. SnakeCase转CamelCase(可选)
如果需要反向转换,同样可以实现对应的类型工具:
// 核心:递归处理字符串,将"_小写字母"转为大写字母并去掉下划线 type SnakeToCamelKey<S extends string> = S extends `${infer Prefix}_${infer Lower}${infer Suffix}` ? `${Prefix}${Uppercase<Lower>}${SnakeToCamelKey<Suffix>}` : S; // 遍历对象所有键,完成snake_case到camelCase的转换,值类型保持不变 type SnakeToCamel<BaseType> = { [Key in keyof BaseType as SnakeToCamelKey<string & Key>]: BaseType[Key] };
使用示例
type consumerSchemaSnakeCase = { category_name: string, product_id: number, is_available: boolean }; // 自动推导camelCase类型 type consumerSchemaCamelCase = SnakeToCamel<consumerSchemaSnakeCase>; // 等价于: // type consumerSchemaCamelCase = { // categoryName: string; // productId: number; // isAvailable: boolean; // }
内容的提问来源于stack exchange,提问作者0xBradock
相关产品推荐
相关产品推荐

