forked from clerk/javascript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.ts
More file actions
102 lines (88 loc) · 3.1 KB
/
Copy pathutils.ts
File metadata and controls
102 lines (88 loc) · 3.1 KB
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
export type SnakeToCamel<T> = T extends `${infer A}_${infer B}`
? `${Uncapitalize<A>}${Capitalize<SnakeToCamel<B>>}`
: T extends object
? { [K in keyof T as SnakeToCamel<K>]: T[K] }
: T;
export type DeepSnakeToCamel<T> = T extends `${infer A}_${infer B}`
? `${Uncapitalize<A>}${Capitalize<DeepSnakeToCamel<B>>}`
: T extends object
? { [K in keyof T as DeepSnakeToCamel<K>]: DeepSnakeToCamel<T[K]> }
: T;
export type DeepCamelToSnake<T> = T extends `${infer C0}${infer R}`
? `${C0 extends Uppercase<C0> ? '_' : ''}${Lowercase<C0>}${DeepCamelToSnake<R>}`
: T extends object
? {
[K in keyof T as DeepCamelToSnake<Extract<K, string>>]: DeepCamelToSnake<T[K]>;
}
: T;
export type CamelToSnake<T> = T extends `${infer C0}${infer R}`
? `${C0 extends Uppercase<C0> ? '_' : ''}${Lowercase<C0>}${CamelToSnake<R>}`
: T extends object
? {
[K in keyof T as CamelToSnake<Extract<K, string>>]: T[K];
}
: T;
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
export type DeepRequired<T> = Required<{
[P in keyof T]: T[P] extends object | undefined ? DeepRequired<Required<T[P]>> : T[P];
}>;
export type Nullable<T, K extends keyof T> = {
[P in keyof T]: P extends K ? T[P] | null : T[P];
};
/**
* Internal type used by RecordToPath
*/
type PathImpl<T, Key extends keyof T> = Key extends string
? T[Key] extends Record<string, any>
?
| `${Key}.${PathImpl<T[Key], Exclude<keyof T[Key], keyof any[]>> & string}`
| `${Key}.${Exclude<keyof T[Key], keyof any[]> & string}`
: never
: never;
/**
* Internal type used by RecordToPath
*/
type PathImpl2<T> = PathImpl<T, keyof T> | keyof T;
/**
* Used to construct a type union containing all the keys (even if nested) of an object defined as const
* const obj = { a: { b: '' }, c: '' } as const;
* type Paths = RecordToPath<typeof obj>
* Paths contains: 'a' | 'a.b' | 'c'
*/
export type RecordToPath<T> = PathImpl2<T> extends string | keyof T ? PathImpl2<T> : keyof T;
/**
* Used to read the value of a string path inside an object defined as const
* const obj = { a: { b: 'hello' }} as const;
* type Value = PathValue<typeof obj, 'a.b'>
* Value is now a union set containing a single type: 'hello'
*/
export type PathValue<T, P extends RecordToPath<T>> = P extends `${infer Key}.${infer Rest}`
? Key extends keyof T
? Rest extends RecordToPath<T[Key]>
? PathValue<T[Key], Rest>
: never
: never
: P extends keyof T
? T[P]
: never;
// eslint-disable-next-line @typescript-eslint/ban-types
type IsSerializable<T> = T extends Function ? false : true;
/**
* Excludes any non-serializable prop from an object
*/
export type Serializable<T> = {
[K in keyof T as IsSerializable<T[K]> extends true ? K : never]: T[K];
};
/**
* Enables autocompletion for a union type, while keeping the ability to use any string
* or type of `T`
*/
export type Autocomplete<U extends T, T = string> = U | (T & Record<never, never>);
/**
* Omit without union flattening
* */
export type Without<T, W> = {
[P in keyof T as Exclude<P, W>]: T[P];
};