Intrinsic string types by ahejlsberg · Pull Request #40580 · microsoft/TypeScript (original) (raw)

Think we can add something like Camelize or SnakeCase to convert from snake_case to camelCase etc? It would be cool if we could define our own somehow.

Would be really sweet if we could finally type a recursive camelize function.

This does it for a fixed word length:

type B = 'hi_mate'; type Camelize = S extends ${infer A}_${infer B} ? ${A}${Capitalize<B>} : unknown;

type C = Camelize;

Is there a way to use spread to do it for many?

Have managed to do it like this but it's hideous:

type Z = 'hi_mate_what_up_good_morning_today';

type Camelize< S

= S extends ${infer A}_${infer B}_${infer C}_${infer D}_${infer E}_${infer F}_${infer G}_${infer H} ? ${A}${Capitalize<B>}${Capitalize<C>}${Capitalize<D>}${Capitalize<E>}${Capitalize<F>}${Capitalize<G>}${Capitalize<H>} : S extends ${infer A}_${infer B}_${infer C}_${infer D}_${infer E}_${infer F}_${infer G} ? ${A}${Capitalize<B>}${Capitalize<C>}${Capitalize<D>}${Capitalize<E>}${Capitalize<F>}${Capitalize<G>} : S extends ${infer A}_${infer B}_${infer C}_${infer D}_${infer E}_${infer F} ? ${A}${Capitalize<B>}${Capitalize<C>}${Capitalize<D>}${Capitalize<E>}${Capitalize<F>} : S extends ${infer A}_${infer B}_${infer C}_${infer D}_${infer E} ? ${A}${Capitalize<B>}${Capitalize<C>}${Capitalize<D>}${Capitalize<E>} : S extends ${infer A}_${infer B}_${infer C}_${infer D} ? ${A}${Capitalize<B>}${Capitalize<C>}${Capitalize<D>} : S extends ${infer A}_${infer B}_${infer C} ? ${A}${Capitalize<B>}${Capitalize<C>} : S extends ${infer A}_${infer B} ? ${A}${Capitalize<B>} : S;

type C = Camelize; // hiMateWhatUpGoodMorningToday

function upperFirst(s: S) { const [head, ...tail] = s; return [head.toUpperCase(), ...tail].join('') as Capitalize; }

const z = upperFirst('hello');

function camelCase(s: S) { const [head, ...tail] = s.split('_'); return ${head}${tail.map(upperFirst).join('')} as Camelize; }

const y = camelCase('hello_mate');

So far so good, now I just have to figure out a way of doing the typing recursively on an object.

Ok, I think I nailed it:

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

Would still be nice to get: Same in reverse, and maybe an implementation that uses spread.

Ok, improved version usingJoin and a modified splitter:

type CapitalizeIf< Condition extends boolean, T extends string

= Condition extends true ? Capitalize : T;

type SplitCamel< S extends string, D extends string, IsTail extends boolean = false

= string extends S ? string[] : S extends '' ? [] : S extends ${infer T}${D}${infer U} ? [CapitalizeIf<IsTail, T>, ...SplitCamel<U, D, true>] : [CapitalizeIf<IsTail, S>];

type Camelize = S extends string ? Join<SplitCamel<S, '_'>, ''> : S;

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