snakeCase.ts

 1import { snakeCase } from "case-anything";
 2
 3// https://stackoverflow.com/questions/60269936/typescript-convert-generic-object-from-snake-to-camel-case
 4
 5// Typescript magic to convert any string from camelCase to snake_case at compile time
 6type SnakeCase<S> =
 7    S extends string ?
 8    S extends `${infer T}${infer U}` ?
 9    `${T extends Capitalize<T> ? "_" : ""}${Lowercase<T>}${SnakeCase<U>}` :
10    S :
11    S;
12
13type SnakeCased<Type> = {
14    [Property in keyof Type as SnakeCase<Property>]: SnakeCased<Type[Property]>
15}
16
17export default function snakeCaseTree<T>(object: T): SnakeCased<T> {
18    const snakeObject: any = {};
19    for (const key in object) {
20        snakeObject[snakeCase(key)] = snakeCaseValue(object[key]);
21    }
22    return snakeObject;
23}
24
25function snakeCaseValue(value: any): any {
26    if (typeof value === "object") {
27        if (Array.isArray(value)) {
28            return value.map(snakeCaseValue);
29        } else {
30            return snakeCaseTree(value);
31        }
32    } else {
33        return value;
34    }
35}