Skip to content

Instantly share code, notes, and snippets.

@steven-schmoll-at
Created September 21, 2021 04:03
Show Gist options
  • Save steven-schmoll-at/1ce3538691b5814e94b6ccea1912e673 to your computer and use it in GitHub Desktop.
Save steven-schmoll-at/1ce3538691b5814e94b6ccea1912e673 to your computer and use it in GitHub Desktop.
A typescript utility type to convert snake_case keys of an interface, to camelCase
/**
* Converts a type string from a snake_case string to PascalCase.
* This will convert all snake case strings including strings with no underscores, or many
*/
export type PascaleFromSnake<String extends string> = String extends `${infer First}_${infer Rest}` ? `${Capitalize<Lowercase<First>>}${PascaleFromSnake<Rest>}` : Capitalize<Lowercase<String>>
/**
* Converts a type string from a snake_case string to camelCase.
* This will convert all snake case strings including strings with no underscores, or many
*/
export type CamelFromSnake<String extends string> = String extends `${infer First}_${infer Rest}` ? `${Lowercase<First>}${PascaleFromSnake<Rest>}` : Lowercase<String>
type InternalMapCamelKeys<T, deep extends boolean> = {
[key in keyof T & string]: {
[transformed in CamelFromSnake<key & string>]: deep extends true ? SnakeToCamelKeys<T[key], deep> : T[key]
}
}
// Creates a union of all value types within the map. This is used to extract out the values from above
type CombineAll<T> = T extends {[name in keyof T]: infer Type} ? Type : never
/**
* Transforms an object with snake_case keys to an object with camelCase keys.
*
* If deep is true, this also transforms the keys of internal classes too.
*/
export type SnakeToCamelKeys<T, deep extends boolean = false> = T extends object ? CombineAll<InternalMapCamelKeys<T, deep>> : T
// Example
//========================
interface Test {
name: string
other_name: string
some_other: {
with_inside: boolean
name: string
}
}
const exampleWithoutInner: SnakeToCamelKeys<Test> = {
name: 'Test',
otherName: 'Something else',
someOther: {
with_inside: false,
name: 'Inside'
}
}
const exampleWithInner: SnakeToCamelKeys<Test, true> = {
name: 'Test',
otherName: 'Something else',
someOther: {
withInside: true,
name: 'Inside'
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment