Let's say I have an interface like this
interface Example {
first_name: string,
last_name: string,
home_town: string,
}
I am looking for a generic like Camelize
that can take Example
and switch all the keys to be valid if they are camelized instead of underscore.
const e: Camelize<Example> = {
firstName: 'string',
lastName: 'string',
homeTown: 'string'
}
Is this possible?
UPDATE for TypeScript 4.5:
With the introduction of tail recursion elimination on conditional types, it is now possible to write a version of Camelize
that converts keys to camel case without running into recursion depth limits as easily as before:
The CamelizeString<T, C>
type uses C
as an accumulator to store intermediate results of turning the snake case string in T
to the camel case string in C
.
type CamelizeString<T extends PropertyKey, C extends string = ""> =
T extends string ? string extends T ? string :
T extends `${infer F}_${infer R}` ?
CamelizeString<Capitalize<R>, `${C}${F}`> : `${C}${T}` : T;
The rest of the code is the same as the version below.
Playground link to code
TypeScript 4.1 introduced template literal types and key remapping in mapped types (see microsoft/TypeScript#40336), so you can achieve it this way:
type CamelizeString<T extends PropertyKey> =
T extends string ? string extends T ? string :
T extends `${infer F}_${infer R}` ? `${F}${Capitalize<CamelizeString<R>>}` : T : T;
type Camelize<T> = { [K in keyof T as CamelizeString<K>]: T[K] }
type CamelizeExample = Camelize<Example>;
/* type CamelizeExample = {
firstName: string;
lastName: string;
homeTown: string;
} */
const e: Camelize<Example> = {
firstName: 'string',
lastName: 'string',
homeTown: 'string'
}
The implementation of CamelizeString<T>
finds the first underscore character ("_"
) in a string T
, removes it, and capitalizes the remainder of the string after recursively calling CamelizeString
on that remainder. And Camelize<T>
remaps each key K
of T
to CamelizeString<K>
.
Playground link to code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With