Skip to content

Commit bf91dc1

Browse files
chore: split, improve and clarify types in type-utils
1 parent 7e38136 commit bf91dc1

File tree

5 files changed

+126
-44
lines changed

5 files changed

+126
-44
lines changed

packages/type-utils/src/array.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Gets the type of the elements in an array.
3+
*
4+
* Example:
5+
* ```
6+
* type A = (number | string)[];
7+
* type E = ArrayElement<A>; // number | string
8+
* ```
9+
*/
10+
export type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType[number];

packages/type-utils/src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
export * from './utils';
2-
export * from './timeout';
1+
export * from './array';
32
export * from './overloads';
3+
export * from './timeout';
4+
export * from './utils';
5+
export * from './object';

packages/type-utils/src/object.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export type GetObjectWithKey<U, K extends PropertyKey> = U extends object
2+
? K extends keyof U
3+
? U
4+
: never
5+
: never;
6+
7+
export type GetObjectWithoutKey<U, K extends PropertyKey> = U extends object
8+
? K extends keyof U
9+
? never
10+
: U
11+
: never;
12+
13+
export type ObjectsOnly<T> = T extends Record<string, unknown> ? T : never;

packages/type-utils/src/overloads.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
export type OverloadImplementations<T, U extends keyof T> = Overloads<T[U]>;
2+
23
export type Overloads<T> = Overloads24<T>;
4+
35
type Overloads24<T> = T extends {
46
(...args: infer A1): infer R1;
57
(...args: infer A2): infer R2;
@@ -53,6 +55,7 @@ type Overloads24<T> = T extends {
5355
(...args: A24) => R24,
5456
]
5557
: Overloads23<T>;
58+
5659
type Overloads23<T> = T extends {
5760
(...args: infer A1): infer R1;
5861
(...args: infer A2): infer R2;
@@ -104,6 +107,7 @@ type Overloads23<T> = T extends {
104107
(...args: A23) => R23,
105108
]
106109
: Overloads22<T>;
110+
107111
type Overloads22<T> = T extends {
108112
(...args: infer A1): infer R1;
109113
(...args: infer A2): infer R2;
@@ -153,6 +157,7 @@ type Overloads22<T> = T extends {
153157
(...args: A22) => R22,
154158
]
155159
: Overloads21<T>;
160+
156161
type Overloads21<T> = T extends {
157162
(...args: infer A1): infer R1;
158163
(...args: infer A2): infer R2;
@@ -200,6 +205,7 @@ type Overloads21<T> = T extends {
200205
(...args: A21) => R21,
201206
]
202207
: Overloads20<T>;
208+
203209
type Overloads20<T> = T extends {
204210
(...args: infer A1): infer R1;
205211
(...args: infer A2): infer R2;
@@ -245,6 +251,7 @@ type Overloads20<T> = T extends {
245251
(...args: A20) => R20,
246252
]
247253
: Overloads19<T>;
254+
248255
type Overloads19<T> = T extends {
249256
(...args: infer A1): infer R1;
250257
(...args: infer A2): infer R2;
@@ -288,6 +295,7 @@ type Overloads19<T> = T extends {
288295
(...args: A19) => R19,
289296
]
290297
: Overloads18<T>;
298+
291299
type Overloads18<T> = T extends {
292300
(...args: infer A1): infer R1;
293301
(...args: infer A2): infer R2;
@@ -329,6 +337,7 @@ type Overloads18<T> = T extends {
329337
(...args: A18) => R18,
330338
]
331339
: Overloads17<T>;
340+
332341
type Overloads17<T> = T extends {
333342
(...args: infer A1): infer R1;
334343
(...args: infer A2): infer R2;
@@ -368,6 +377,7 @@ type Overloads17<T> = T extends {
368377
(...args: A17) => R17,
369378
]
370379
: Overloads16<T>;
380+
371381
type Overloads16<T> = T extends {
372382
(...args: infer A1): infer R1;
373383
(...args: infer A2): infer R2;
@@ -405,6 +415,7 @@ type Overloads16<T> = T extends {
405415
(...args: A16) => R16,
406416
]
407417
: Overloads15<T>;
418+
408419
type Overloads15<T> = T extends {
409420
(...args: infer A1): infer R1;
410421
(...args: infer A2): infer R2;
@@ -440,6 +451,7 @@ type Overloads15<T> = T extends {
440451
(...args: A15) => R15,
441452
]
442453
: Overloads14<T>;
454+
443455
type Overloads14<T> = T extends {
444456
(...args: infer A1): infer R1;
445457
(...args: infer A2): infer R2;
@@ -473,6 +485,7 @@ type Overloads14<T> = T extends {
473485
(...args: A14) => R14,
474486
]
475487
: Overloads13<T>;
488+
476489
type Overloads13<T> = T extends {
477490
(...args: infer A1): infer R1;
478491
(...args: infer A2): infer R2;
@@ -504,6 +517,7 @@ type Overloads13<T> = T extends {
504517
(...args: A13) => R13,
505518
]
506519
: Overloads12<T>;
520+
507521
type Overloads12<T> = T extends {
508522
(...args: infer A1): infer R1;
509523
(...args: infer A2): infer R2;
@@ -533,6 +547,7 @@ type Overloads12<T> = T extends {
533547
(...args: A12) => R12,
534548
]
535549
: Overloads11<T>;
550+
536551
type Overloads11<T> = T extends {
537552
(...args: infer A1): infer R1;
538553
(...args: infer A2): infer R2;
@@ -560,6 +575,7 @@ type Overloads11<T> = T extends {
560575
(...args: A11) => R11,
561576
]
562577
: Overloads10<T>;
578+
563579
type Overloads10<T> = T extends {
564580
(...args: infer A1): infer R1;
565581
(...args: infer A2): infer R2;
@@ -585,6 +601,7 @@ type Overloads10<T> = T extends {
585601
(...args: A10) => R10,
586602
]
587603
: Overloads9<T>;
604+
588605
type Overloads9<T> = T extends {
589606
(...args: infer A1): infer R1;
590607
(...args: infer A2): infer R2;
@@ -608,6 +625,7 @@ type Overloads9<T> = T extends {
608625
(...args: A9) => R9,
609626
]
610627
: Overloads8<T>;
628+
611629
type Overloads8<T> = T extends {
612630
(...args: infer A1): infer R1;
613631
(...args: infer A2): infer R2;
@@ -629,6 +647,7 @@ type Overloads8<T> = T extends {
629647
(...args: A8) => R8,
630648
]
631649
: Overloads7<T>;
650+
632651
type Overloads7<T> = T extends {
633652
(...args: infer A1): infer R1;
634653
(...args: infer A2): infer R2;
@@ -648,6 +667,7 @@ type Overloads7<T> = T extends {
648667
(...args: A7) => R7,
649668
]
650669
: Overloads6<T>;
670+
651671
type Overloads6<T> = T extends {
652672
(...args: infer A1): infer R1;
653673
(...args: infer A2): infer R2;
@@ -665,6 +685,7 @@ type Overloads6<T> = T extends {
665685
(...args: A6) => R6,
666686
]
667687
: Overloads5<T>;
688+
668689
type Overloads5<T> = T extends {
669690
(...args: infer A1): infer R1;
670691
(...args: infer A2): infer R2;
@@ -680,6 +701,7 @@ type Overloads5<T> = T extends {
680701
(...args: A5) => R5,
681702
]
682703
: Overloads4<T>;
704+
683705
type Overloads4<T> = T extends {
684706
(...args: infer A1): infer R1;
685707
(...args: infer A2): infer R2;
@@ -688,19 +710,22 @@ type Overloads4<T> = T extends {
688710
}
689711
? [(...args: A1) => R1, (...args: A2) => R2, (...args: A3) => R3, (...args: A4) => R4]
690712
: Overloads3<T>;
713+
691714
type Overloads3<T> = T extends {
692715
(...args: infer A1): infer R1;
693716
(...args: infer A2): infer R2;
694717
(...args: infer A3): infer R3;
695718
}
696719
? [(...args: A1) => R1, (...args: A2) => R2, (...args: A3) => R3]
697720
: Overloads2<T>;
721+
698722
type Overloads2<T> = T extends {
699723
(...args: infer A1): infer R1;
700724
(...args: infer A2): infer R2;
701725
}
702726
? [(...args: A1) => R1, (...args: A2) => R2]
703727
: Overloads1<T>;
728+
704729
type Overloads1<T> = T extends {
705730
(...args: infer A1): infer R1;
706731
}

packages/type-utils/src/utils.ts

Lines changed: 74 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,55 @@
1-
// make key required
2-
1+
/**
2+
* Make property of the object required.
3+
*
4+
* Example:
5+
* ```
6+
* type T = { a?: number };
7+
* const t: RequiredKey<T, 'a'> = { a: 0 }; // 'a' is mandatory
8+
* ```
9+
*/
310
export type RequiredKey<M, K extends keyof M> = Omit<M, K> & Required<Pick<M, K>>;
411

5-
// object values types
12+
/**
13+
* Get type of the object values.
14+
*
15+
* Example:
16+
* ```
17+
* type T = { a: number; b: string };
18+
* type V: ObjectValues<T>; // number | string
19+
* ```
20+
*/
621
export type ObjectValues<T extends { [key: string]: any }> = T[keyof T];
722

8-
// all keys of types in an union
23+
/**
24+
* All keys of types in a union.
25+
*
26+
* Example:
27+
* ```
28+
* type T = { a: number; b: string };
29+
* type K: Keys<T>; // 'a' | 'b'
30+
* ```
31+
*/
932
export type Keys<T> = T extends any ? keyof T : never;
1033

11-
// remove the keys while keeping the union
34+
/**
35+
* Distributes the Omit across a union. using distributive conditional types to achieve this:
36+
* @see: https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
37+
* @source: https://stackoverflow.com/questions/57103834/typescript-omit-a-property-from-all-interfaces-in-a-union-but-keep-the-union-s#answer-57103940
38+
*
39+
* Example:
40+
* ```
41+
* type T = { remove: string; keep1: number } | { remove: string; keep2: boolean };
42+
* type W = Without<T, 'remove'>;
43+
* const w: W = { keep1: 1, keep2: true };
44+
* ```
45+
*/
1246
export type Without<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
1347

14-
// array element type
15-
export type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType[number];
16-
17-
// const with optional types
48+
/**
49+
* Const with optional types.
50+
* Todo: add example and better explanation.
51+
* It has exactly 1 usage so maybe this shall even be here in the utils package
52+
*/
1853
export type ConstWithOptionalFields<
1954
Const extends { [key: string]: any },
2055
Fields extends string | number | symbol,
@@ -30,49 +65,46 @@ export type ConstWithOptionalFields<
3065
};
3166
};
3267

33-
// Extract item from union
34-
export type ItemExtractor<M> = Extract<M, { type: M }>;
35-
36-
// Unwrap type from Promise
37-
export type Await<T> = T extends {
38-
then(onfulfilled?: (value: infer U) => unknown): unknown;
39-
}
40-
? U
41-
: T;
42-
68+
/**
69+
* Recursively makes all properties of the object optional. If the nested property is an object,
70+
* it will make its properties optional as well.
71+
*
72+
* Example:
73+
* ```
74+
* type T = { a: number; b: { c: string; d: number } };
75+
* type P = DeepPartial<T>;
76+
* const p: P = { b: { d: 1 } }; // As everything is deeply optional
77+
* ```
78+
*/
4379
export type DeepPartial<T> = T extends () => any
4480
? T
4581
: T extends { [key: string]: any }
4682
? { [P in keyof T]?: DeepPartial<T[P]> }
4783
: T;
4884

85+
/**
86+
* Type containing all primitive types in TypeScript.
87+
*/
4988
export type PrimitiveType = string | number | boolean | Date | null | undefined;
5089

51-
// Record<K, T> with optional key and required value.
52-
// example of using partial union as keys:
53-
// const p: PartialRecord<'a' | 'b' | 'c', string>; = { b: 'value' };
54-
export type PartialRecord<K extends keyof any, T> = {
55-
[P in K]?: T;
56-
};
57-
58-
// distributive conditional types to the rescue! This way we can infer union literal type from ReturnType but exclude undefined
90+
/**
91+
* Record<K, T> with optional key and required value.
92+
*
93+
* Example:
94+
* ```
95+
* const p: PartialRecord<'a' | 'b' | 'c', string>; = { b: 'value' };
96+
* ```
97+
*/
98+
export type PartialRecord<K extends keyof any, T> = { [P in K]?: T };
99+
100+
/**
101+
* This infers the union literal type from ReturnType but exclude undefined
102+
*/
59103
export type DefinedUnionMember<T> = T extends string ? T : never;
60104

61-
export type GetObjectWithKey<U, K extends PropertyKey> = U extends object
62-
? K extends keyof U
63-
? U
64-
: never
65-
: never;
66-
export type GetObjectWithoutKey<U, K extends PropertyKey> = U extends object
67-
? K extends keyof U
68-
? never
69-
: U
70-
: never;
71-
72-
export type ObjectsOnly<T> = T extends Record<string, unknown> ? T : never;
73-
74-
// map object `T` to a narrowed type with only those entries that match given `ValueFilter` type
105+
/**
106+
* Map object `T` to a narrowed type with only those entries that match given `ValueFilter` type
107+
*/
75108
export type FilterPropertiesByType<T, ValueFilter> = {
76109
[Key in keyof T as T[Key] extends ValueFilter ? Key : never]: T[Key];
77110
};
78-

0 commit comments

Comments
 (0)