解决方案
Playground
这可以通过 TypeScript 4.1 中的 template literal types 实现(另请参阅 snake_case):
type SnakeToCamelCase<S extends string> =
S extends `${infer T}_${infer U}` ?
`${T}${Capitalize<SnakeToCamelCase<U>>}` :
S
type T11 = SnakeToCamelCase<"hello"> // "hello"
type T12 = SnakeToCamelCase<"hello_world"> // "helloWorld"
type T13 = SnakeToCamelCase<"hello_ts_world"> // "helloTsWorld"
type T14 = SnakeToCamelCase<"hello_world" | "foo_bar">// "helloWorld" | "fooBar"
type T15 = SnakeToCamelCase<string> // string
type T16 = SnakeToCamelCase<`the_answer_is_${N}`>//"theAnswerIs42" (type N = 42)
然后您将能够使用key remapping in mapped types 构造新的记录类型:
type OutputType = {[K in keyof InputType as SnakeToCamelCase<K>]: InputType[K]}
/*
type OutputType = {
snakeCaseKey1: number;
snakeCaseKey2: string;
}
*/
扩展
反转类型
type CamelToSnakeCase<S extends string> =
S extends `${infer T}${infer U}` ?
`${T extends Capitalize<T> ? "_" : ""}${Lowercase<T>}${CamelToSnakeCase<U>}` :
S
type T21 = CamelToSnakeCase<"hello"> // "hello"
type T22 = CamelToSnakeCase<"helloWorld"> // "hello_world"
type T23 = CamelToSnakeCase<"helloTsWorld"> // "hello_ts_world"
Pascal case、Kebab case 和 inversions
一旦你得到以上类型,使用intrinsic string typesCapitalize和Uncapitalize就可以很简单地在它们和其他情况之间进行转换:
type CamelToPascalCase<S extends string> = Capitalize<S>
type PascalToCamelCase<S extends string> = Uncapitalize<S>
type PascalToSnakeCase<S extends string> = CamelToSnakeCase<Uncapitalize<S>>
type SnakeToPascalCase<S extends string> = Capitalize<SnakeToCamelCase<S>>
对于kebab case,将snake case类型的_替换为-。
转换嵌套属性
type SnakeToCamelCaseNested<T> = T extends object ? {
[K in keyof T as SnakeToCamelCase<K & string>]: SnakeToCamelCaseNested<T[K]>
} : T
“类型实例化太深,可能无限。”
这个错误可能发生在很长的字符串上。您可以一次性处理多个子项,以将类型递归限制在编译器可接受的范围内。例如。 SnakeToCamelCaseXXL:
Playground
type SnakeToCamelCaseXXL<S extends string> =
S extends `${infer T}_${infer U}_${infer V}` ?
`${T}${Capitalize<U>}${Capitalize<SnakeToCamelCaseXXL<V>>}` :
S extends `${infer T}_${infer U}` ?
`${T}${Capitalize<SnakeToCamelCaseXXL<U>>}` :
S
注意:在第一个条件中,T 和 U 各推断一个子项,而V 推断字符串的其余部分。
更新:TS 4.5 将类型实例化深度限制从 50 提高到 100,因此新版本不需要此编译器技巧。对于更复杂的情况,您现在还可以使用tail recursive evaluation。