ARTICLE AD BOX
I'm trying to write the following function, and can't get the type definition to work out:
export function deepMapKeys<T, S extends string>( obj: T, keyTransform: (s: string) => S, ): DeepMapKeys<T, (arg: string) => S> { return null as any } type DeepMapKeys<T, F extends (s: string) => string> = T extends Array<infer U> ? Array<DeepMapKeys<U, F>> : T extends object ? { [K in keyof T as ReturnType<F> & string]: DeepMapKeys<T[K], F> } : TIs this even possible to do with TypeScript or is there some limitation that will be hit?
Here's a full version that can be run with tsc:
type CamelCase<S extends string> = S extends `${infer S1}_${infer S2}` ? `${S1}${Capitalize<CamelCase<S2>>}` : S export const snakeToCamelCase = <S extends string>(s: S): CamelCase<S> => s.replace(/(_(\w))/g, (m) => m[1].toUpperCase()) as CamelCase<S> type DeepMapKeys<T, F extends (s: string) => string> = T extends Array<infer U> ? Array<DeepMapKeys<U, F>> : T extends object ? { [K in keyof T as ReturnType<F> & string]: DeepMapKeys<T[K], F> } : T export function deepMapKeys<T, S extends string>( obj: T, keyTransform: (s: string) => S, ): DeepMapKeys<T, (arg: string) => S> { return null as any } const input = { hello_world: 'anything', } const result = deepMapKeys(input, snakeToCamelCase) function testType(input: never) {} testType(result)You can see here that the resulting type { [x: string]: string; } instead of { helloWorld: string }.
$ ./node_modules/.bin/tsc --version Version 5.9.3 $ ./node_modules/.bin/tsc src/test.ts src/test.ts:32:10 - error TS2345: Argument of type '{ [x: string]: string; }' is not assignable to parameter of type 'never'. 32 testType(result) ~~~~~~ Found 1 error in src/test.ts:32