Skip to content

Instantly share code, notes, and snippets.

@lazuee
Created August 11, 2022 13:50
Show Gist options
  • Save lazuee/7f4b9bdaf0d3e310f8e908459d800637 to your computer and use it in GitHub Desktop.
Save lazuee/7f4b9bdaf0d3e310f8e908459d800637 to your computer and use it in GitHub Desktop.
PascalCase to SentenceCase
type Words<S extends string> = S extends S ? string extends S ? string[] : WordsAgg<S, []> : never;
type WordsAgg<S extends string, L extends string[]> = S extends ""
? L
: S extends `${AsciiUpper}${AsciiLower}${string}`
? PascalWord<S, L>
: S extends `${AsciiUpper}${string}`
? UpperWord<S, L>
: S extends `${AsciiLower}${string}`
? CharsetWord<S, L, AsciiLower>
: S extends `${AsciiDigit}${string}`
? CharsetWord<S, L, AsciiDigit>
: S extends `${string}${infer Tail}`
? WordsAgg<Tail, L>
: never;
type PascalWord<
S extends string,
L extends string[],
> = S extends `${infer Head extends AsciiUpper}${infer Tail extends `${AsciiLower}${string}`}`
? CharsetWord<Tail, L, AsciiLower, Head>
: never;
type UpperWord<
S extends string,
L extends string[],
W extends string = "",
> = S extends `${AsciiUpper}${AsciiLower}${string}` ? WordsAgg<S, [...L, W]> : S extends `${infer Next extends AsciiUpper}${infer Tail}` ? UpperWord<Tail, L, `${W}${Next}`> : WordsAgg<S, [...L, W]>;
type CharsetWord<
S extends string,
L extends string[],
C extends string,
W extends string = "",
> = S extends `${infer Next extends C}${infer Tail}` ? CharsetWord<Tail, L, C, `${W}${Next}`> : WordsAgg<S, [...L, W]>;
type AsciiDigit = | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type AsciiUpper = | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z";
type AsciiLower = Lowercase<AsciiUpper>;
type ApplyCapitalize<W extends string[], Acc extends string> = W extends []
? Acc
: W extends [infer T extends string, ...infer U extends string[]]
? ApplyCapitalize<U, `${Acc} ${Capitalize<T>}`>
: null;
type TrimStart<T extends string> = T extends ` ${infer R}` ? TrimStart<R> : T;
type PascalToSentenceCase<S extends string> = TrimStart<S extends S ? string extends S ? string : ApplyCapitalize<Words<S>, ""> : never>
//Useful for discord.js PascalCase Enums
type T1 = PascalToSentenceCase<"SendMessages">
type T2 = PascalToSentenceCase<"SendTTSMessages">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment