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.