forked from ts-essentials/ts-essentials
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
68 lines (54 loc) · 2.45 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
type IsStringLiteral<Type> = Type extends string ? (string extends Type ? false : true) : false;
type WordInCamelCase<Type, Word extends string = ""> = Type extends `${Word}${infer NextCharacter}${infer _}`
? NextCharacter extends Capitalize<NextCharacter>
? Word
: WordInCamelCase<Type, `${Word}${NextCharacter}`>
: Word;
type Separator = "_" | "-";
type IncludesSeparator<Type> = Type extends `${string}${Separator}${string}` ? true : false;
type IsOneWord<Type> = Type extends Lowercase<Type & string>
? true
: Type extends Uppercase<Type & string>
? true
: false;
type IsCamelCase<Type> = Type extends Uncapitalize<Type & string> ? true : false;
type IsPascalCase<Type> = Type extends Capitalize<Type & string> ? true : false;
/** snake_case, CONSTANT_CASE, kebab-case or COBOL-CASE */
type SeparatorCaseParser<
Type,
Tuple extends readonly any[] = [],
> = Type extends `${infer Word}${Separator}${infer Tail}`
? SeparatorCaseParser<Tail, [...Tuple, Lowercase<Word>]>
: Type extends `${infer Word}`
? [...Tuple, Lowercase<Word>]
: Tuple;
type CamelCaseParser<Type, Tuple extends readonly any[] = []> = Type extends ""
? Tuple
: Type extends `${WordInCamelCase<Type>}${infer Tail}`
? Type extends `${infer Word}${Tail}`
? CamelCaseParser<Uncapitalize<Tail>, [...Tuple, Lowercase<Word>]>
: never
: never;
// Convert first character of string literal type to lowercase and reuse CamelCaseParser
type PascalCaseParser<Type> = Type extends string ? CamelCaseParser<Uncapitalize<Type>> : never;
type SplitAnyCase<Type> = IncludesSeparator<Type> extends true
? SeparatorCaseParser<Type>
: IsOneWord<Type> extends true
? [Lowercase<Type & string>]
: IsCamelCase<Type> extends true
? CamelCaseParser<Type>
: IsPascalCase<Type> extends true
? PascalCaseParser<Type>
: [];
type PascalCapitalizer<Type, Tuple extends readonly any[] = []> = Type extends [infer Head, ...infer Tail]
? Head extends string
? PascalCapitalizer<Tail, [...Tuple, Capitalize<Head>]>
: PascalCapitalizer<Tail, Tuple>
: Tuple;
type CamelCapitalizer<Type> = Type extends [infer First, ...infer Tail] ? PascalCapitalizer<Tail, [First]> : [];
type Join<Type, JoinedString extends string = ""> = Type extends [infer Head, ...infer Tail]
? Head extends string
? Join<Tail, `${JoinedString}${Head}`>
: Join<Tail>
: JoinedString;
export type CamelCase<Type> = IsStringLiteral<Type> extends true ? Join<CamelCapitalizer<SplitAnyCase<Type>>> : Type;