I'm new to typescript but I want to create a mapped type that converts keys from another type. Specifically, say I have a type where all the keys are snake-cased, how can I create a type where they are all camel-cased?
I thought I could do something like
type CamelCase<T> = {
[_.camelCase(P in keyof T)]: T[P];
}
type MyCamelCaseType = CamelCase<SnakeCaseType>;
But TS doesn't like this. How can I transform the keys of an existing type to create a new type in this way?
In Typescript 4.1, template literal types got quite an upgrade. This is a problem I have wanting to be solved for a while and with a bit of tweaking managed to come up with this:
type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}`
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
: Lowercase<S>
type KeysToCamelCase<T> = {
[K in keyof T as CamelCase<string &K>]: T[K] extends {} ? KeysToCamelCase<T[K]> : T[K]
}
interface SnakeCase {
bar_value: string;
baz_value: {
blah_test: number;
}
}
const transformed: KeysToCamelCase<SnakeCase> = {
bazValue: {
blahTest: 2
},
barValue: 'test'
}
I can recommend reading: https://dev.to/phenomnominal/i-need-to-learn-about-typescript-template-literal-types-51po and also trying some of these Typescript challenges https://github.com/type-challenges/type-challenges to learn more about these literal types.
In case you have an object with nested arrays in it, you can wrap it a bit more. Based on Max Eisenhardts answer.
We can check on an Array type, and if so, take the object type of that Array in the already existing functionality.
If we don't do this, array functions will be marked as not callable.
type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}`
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
: Lowercase<S>
type ObjectToCamel<T> = {
[K in keyof T as CamelCase<string &K>]: T[K] extends Record<string, any> ? KeysToCamelCase<T[K]> : T[K]
}
type KeysToCamelCase<T> = {
[K in keyof T as CamelCase<string &K>]: T[K] extends Array<any> ? KeysToCamelCase<T[K][number]>[] : ObjectToCamel<T[K]>
}
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