6

Let's say I have an interface like this

interface Example {
    first_name: string,
    last_name: string,
    home_town: string,
}

I am looking for a generic like Camelize that can take Example and switch all the keys to be valid if they are camelized instead of underscore.

const e: Camelize<Example> = {
  firstName: 'string',
  lastName: 'string',
  homeTown: 'string'
}

Is this possible?

3

2 Answers 2

25

UPDATE for TypeScript 4.5:

With the introduction of tail recursion elimination on conditional types, it is now possible to write a version of Camelize that converts keys to camel case without running into recursion depth limits as easily as before:

The CamelizeString<T, C> type uses C as an accumulator to store intermediate results of turning the snake case string in T to the camel case string in C.

type CamelizeString<T extends PropertyKey, C extends string = ""> =
    T extends string ? string extends T ? string :
    T extends `${infer F}_${infer R}` ?
    CamelizeString<Capitalize<R>, `${C}${F}`> : `${C}${T}` : T;

The rest of the code is the same as the version below.

Playground link to code


TypeScript 4.1 introduced template literal types and key remapping in mapped types (see microsoft/TypeScript#40336), so you can achieve it this way:

type CamelizeString<T extends PropertyKey> = 
    T extends string ? string extends T ? string :
    T extends `${infer F}_${infer R}` ? `${F}${Capitalize<CamelizeString<R>>}` : T : T;

type Camelize<T> = { [K in keyof T as CamelizeString<K>]: T[K] }

type CamelizeExample = Camelize<Example>;
/* type CamelizeExample = {
    firstName: string;
    lastName: string;
    homeTown: string;
} */

const e: Camelize<Example> = {
    firstName: 'string',
    lastName: 'string',
    homeTown: 'string'
}

The implementation of CamelizeString<T> finds the first underscore character ("_") in a string T, removes it, and capitalizes the remainder of the string after recursively calling CamelizeString on that remainder. And Camelize<T> remaps each key K of T to CamelizeString<K>.

Playground link to code

Sign up to request clarification or add additional context in comments.

Comments

6

FWIW, I ran into some issues with the types from @jcalz's answer. I found CamelCasedProperties and SnakeCasedProperties from https://github.com/sindresorhus/type-fest to work well so far.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.