1 | import { Primitive } from './aliases-and-guards';
|
2 | /**
|
3 | * Credits to all the people who given inspiration and shared some very useful code snippets
|
4 | * in the following github issue: https://github.com/Microsoft/TypeScript/issues/12215
|
5 | */
|
6 | /**
|
7 | * SetIntersection (same as Extract)
|
8 | * @desc Set intersection of given union types `A` and `B`
|
9 | * @example
|
10 | * // Expect: "2" | "3"
|
11 | * SetIntersection<'1' | '2' | '3', '2' | '3' | '4'>;
|
12 | *
|
13 | * // Expect: () => void
|
14 | * SetIntersection<string | number | (() => void), Function>;
|
15 | */
|
16 | export declare type SetIntersection<A, B> = A extends B ? A : never;
|
17 | /**
|
18 | * SetDifference (same as Exclude)
|
19 | * @desc Set difference of given union types `A` and `B`
|
20 | * @example
|
21 | * // Expect: "1"
|
22 | * SetDifference<'1' | '2' | '3', '2' | '3' | '4'>;
|
23 | *
|
24 | * // Expect: string | number
|
25 | * SetDifference<string | number | (() => void), Function>;
|
26 | */
|
27 | export declare type SetDifference<A, B> = A extends B ? never : A;
|
28 | /**
|
29 | * SetComplement
|
30 | * @desc Set complement of given union types `A` and (it's subset) `A1`
|
31 | * @example
|
32 | * // Expect: "1"
|
33 | * SetComplement<'1' | '2' | '3', '2' | '3'>;
|
34 | */
|
35 | export declare type SetComplement<A, A1 extends A> = SetDifference<A, A1>;
|
36 | /**
|
37 | * SymmetricDifference
|
38 | * @desc Set difference of union and intersection of given union types `A` and `B`
|
39 | * @example
|
40 | * // Expect: "1" | "4"
|
41 | * SymmetricDifference<'1' | '2' | '3', '2' | '3' | '4'>;
|
42 | */
|
43 | export declare type SymmetricDifference<A, B> = SetDifference<A | B, A & B>;
|
44 | /**
|
45 | * NonUndefined
|
46 | * @desc Exclude undefined from set `A`
|
47 | * @example
|
48 | * // Expect: "string | null"
|
49 | * SymmetricDifference<string | null | undefined>;
|
50 | */
|
51 | export declare type NonUndefined<A> = A extends undefined ? never : A;
|
52 | /**
|
53 | * NonNullable
|
54 | * @desc Exclude undefined and null from set `A`
|
55 | * @example
|
56 | * // Expect: "string"
|
57 | * SymmetricDifference<string | null | undefined>;
|
58 | */
|
59 | /**
|
60 | * FunctionKeys
|
61 | * @desc Get union type of keys that are functions in object type `T`
|
62 | * @example
|
63 | * type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
|
64 | *
|
65 | * // Expect: "setName | someFn"
|
66 | * type Keys = FunctionKeys<MixedProps>;
|
67 | */
|
68 | export declare type FunctionKeys<T extends object> = {
|
69 | [K in keyof T]-?: NonUndefined<T[K]> extends Function ? K : never;
|
70 | }[keyof T];
|
71 | /**
|
72 | * NonFunctionKeys
|
73 | * @desc Get union type of keys that are non-functions in object type `T`
|
74 | * @example
|
75 | * type MixedProps = {name: string; setName: (name: string) => void; someKeys?: string; someFn?: (...args: any) => any;};
|
76 | *
|
77 | * // Expect: "name | someKey"
|
78 | * type Keys = NonFunctionKeys<MixedProps>;
|
79 | */
|
80 | export declare type NonFunctionKeys<T extends object> = {
|
81 | [K in keyof T]-?: NonUndefined<T[K]> extends Function ? never : K;
|
82 | }[keyof T];
|
83 | /**
|
84 | * MutableKeys
|
85 | * @desc Get union type of keys that are mutable in object type `T`
|
86 | * Credit: Matt McCutchen
|
87 | * https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript
|
88 | * @example
|
89 | * type Props = { readonly foo: string; bar: number };
|
90 | *
|
91 | * // Expect: "bar"
|
92 | * type Keys = MutableKeys<Props>;
|
93 | */
|
94 | export declare type MutableKeys<T extends object> = {
|
95 | [P in keyof T]-?: IfEquals<{
|
96 | [Q in P]: T[P];
|
97 | }, {
|
98 | -readonly [Q in P]: T[P];
|
99 | }, P>;
|
100 | }[keyof T];
|
101 | export declare type WritableKeys<T extends object> = MutableKeys<T>;
|
102 | /**
|
103 | * ReadonlyKeys
|
104 | * @desc Get union type of keys that are readonly in object type `T`
|
105 | * Credit: Matt McCutchen
|
106 | * https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript
|
107 | * @example
|
108 | * type Props = { readonly foo: string; bar: number };
|
109 | *
|
110 | * // Expect: "foo"
|
111 | * type Keys = ReadonlyKeys<Props>;
|
112 | */
|
113 | export declare type ReadonlyKeys<T extends object> = {
|
114 | [P in keyof T]-?: IfEquals<{
|
115 | [Q in P]: T[P];
|
116 | }, {
|
117 | -readonly [Q in P]: T[P];
|
118 | }, never, P>;
|
119 | }[keyof T];
|
120 | declare type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B;
|
121 | /**
|
122 | * RequiredKeys
|
123 | * @desc Get union type of keys that are required in object type `T`
|
124 | * @see https://stackoverflow.com/questions/52984808/is-there-a-way-to-get-all-required-properties-of-a-typescript-object
|
125 | * @example
|
126 | * type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; };
|
127 | *
|
128 | * // Expect: "req" | "reqUndef"
|
129 | * type Keys = RequiredKeys<Props>;
|
130 | */
|
131 | export declare type RequiredKeys<T> = {
|
132 | [K in keyof T]-?: {} extends Pick<T, K> ? never : K;
|
133 | }[keyof T];
|
134 | /**
|
135 | * OptionalKeys
|
136 | * @desc Get union type of keys that are optional in object type `T`
|
137 | * @see https://stackoverflow.com/questions/52984808/is-there-a-way-to-get-all-required-properties-of-a-typescript-object
|
138 | * @example
|
139 | * type Props = { req: number; reqUndef: number | undefined; opt?: string; optUndef?: number | undefined; };
|
140 | *
|
141 | * // Expect: "opt" | "optUndef"
|
142 | * type Keys = OptionalKeys<Props>;
|
143 | */
|
144 | export declare type OptionalKeys<T> = {
|
145 | [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
|
146 | }[keyof T];
|
147 | /**
|
148 | * PickByValue
|
149 | * @desc From `T` pick a set of properties by value matching `ValueType`.
|
150 | * Credit: [Piotr Lewandowski](https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c)
|
151 | * @example
|
152 | * type Props = { req: number; reqUndef: number | undefined; opt?: string; };
|
153 | *
|
154 | * // Expect: { req: number }
|
155 | * type Props = PickByValue<Props, number>;
|
156 | * // Expect: { req: number; reqUndef: number | undefined; }
|
157 | * type Props = PickByValue<Props, number | undefined>;
|
158 | */
|
159 | export declare type PickByValue<T, ValueType> = Pick<T, {
|
160 | [Key in keyof T]-?: T[Key] extends ValueType ? Key : never;
|
161 | }[keyof T]>;
|
162 | /**
|
163 | * PickByValueExact
|
164 | * @desc From `T` pick a set of properties by value matching exact `ValueType`.
|
165 | * @example
|
166 | * type Props = { req: number; reqUndef: number | undefined; opt?: string; };
|
167 | *
|
168 | * // Expect: { req: number }
|
169 | * type Props = PickByValueExact<Props, number>;
|
170 | * // Expect: { reqUndef: number | undefined; }
|
171 | * type Props = PickByValueExact<Props, number | undefined>;
|
172 | */
|
173 | export declare type PickByValueExact<T, ValueType> = Pick<T, {
|
174 | [Key in keyof T]-?: [ValueType] extends [T[Key]] ? [T[Key]] extends [ValueType] ? Key : never : never;
|
175 | }[keyof T]>;
|
176 | /**
|
177 | * Omit (complements Pick)
|
178 | * @desc From `T` remove a set of properties by key `K`
|
179 | * @example
|
180 | * type Props = { name: string; age: number; visible: boolean };
|
181 | *
|
182 | * // Expect: { name: string; visible: boolean; }
|
183 | * type Props = Omit<Props, 'age'>;
|
184 | */
|
185 | export declare type Omit<T, K extends keyof any> = Pick<T, SetDifference<keyof T, K>>;
|
186 | /**
|
187 | * OmitByValue
|
188 | * @desc From `T` remove a set of properties by value matching `ValueType`.
|
189 | * Credit: [Piotr Lewandowski](https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c)
|
190 | * @example
|
191 | * type Props = { req: number; reqUndef: number | undefined; opt?: string; };
|
192 | *
|
193 | * // Expect: { reqUndef: number | undefined; opt?: string; }
|
194 | * type Props = OmitByValue<Props, number>;
|
195 | * // Expect: { opt?: string; }
|
196 | * type Props = OmitByValue<Props, number | undefined>;
|
197 | */
|
198 | export declare type OmitByValue<T, ValueType> = Pick<T, {
|
199 | [Key in keyof T]-?: T[Key] extends ValueType ? never : Key;
|
200 | }[keyof T]>;
|
201 | /**
|
202 | * OmitByValueExact
|
203 | * @desc From `T` remove a set of properties by value matching exact `ValueType`.
|
204 | * @example
|
205 | * type Props = { req: number; reqUndef: number | undefined; opt?: string; };
|
206 | *
|
207 | * // Expect: { reqUndef: number | undefined; opt?: string; }
|
208 | * type Props = OmitByValueExact<Props, number>;
|
209 | * // Expect: { req: number; opt?: string }
|
210 | * type Props = OmitByValueExact<Props, number | undefined>;
|
211 | */
|
212 | export declare type OmitByValueExact<T, ValueType> = Pick<T, {
|
213 | [Key in keyof T]-?: [ValueType] extends [T[Key]] ? [T[Key]] extends [ValueType] ? never : Key : Key;
|
214 | }[keyof T]>;
|
215 | /**
|
216 | * Intersection
|
217 | * @desc From `T` pick properties that exist in `U`
|
218 | * @example
|
219 | * type Props = { name: string; age: number; visible: boolean };
|
220 | * type DefaultProps = { age: number };
|
221 | *
|
222 | * // Expect: { age: number; }
|
223 | * type DuplicateProps = Intersection<Props, DefaultProps>;
|
224 | */
|
225 | export declare type Intersection<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U> & Extract<keyof U, keyof T>>;
|
226 | /**
|
227 | * Diff
|
228 | * @desc From `T` remove properties that exist in `U`
|
229 | * @example
|
230 | * type Props = { name: string; age: number; visible: boolean };
|
231 | * type DefaultProps = { age: number };
|
232 | *
|
233 | * // Expect: { name: string; visible: boolean; }
|
234 | * type DiffProps = Diff<Props, DefaultProps>;
|
235 | */
|
236 | export declare type Diff<T extends object, U extends object> = Pick<T, SetDifference<keyof T, keyof U>>;
|
237 | /**
|
238 | * Subtract
|
239 | * @desc From `T` remove properties that exist in `T1` (`T1` has a subset of the properties of `T`)
|
240 | * @example
|
241 | * type Props = { name: string; age: number; visible: boolean };
|
242 | * type DefaultProps = { age: number };
|
243 | *
|
244 | * // Expect: { name: string; visible: boolean; }
|
245 | * type RestProps = Subtract<Props, DefaultProps>;
|
246 | */
|
247 | export declare type Subtract<T extends T1, T1 extends object> = Pick<T, SetComplement<keyof T, keyof T1>>;
|
248 | /**
|
249 | * Overwrite
|
250 | * @desc From `U` overwrite properties to `T`
|
251 | * @example
|
252 | * type Props = { name: string; age: number; visible: boolean };
|
253 | * type NewProps = { age: string; other: string };
|
254 | *
|
255 | * // Expect: { name: string; age: string; visible: boolean; }
|
256 | * type ReplacedProps = Overwrite<Props, NewProps>;
|
257 | */
|
258 | export declare type Overwrite<T extends object, U extends object, I = Diff<T, U> & Intersection<U, T>> = Pick<I, keyof I>;
|
259 | /**
|
260 | * Assign
|
261 | * @desc From `U` assign properties to `T` (just like object assign)
|
262 | * @example
|
263 | * type Props = { name: string; age: number; visible: boolean };
|
264 | * type NewProps = { age: string; other: string };
|
265 | *
|
266 | * // Expect: { name: string; age: number; visible: boolean; other: string; }
|
267 | * type ExtendedProps = Assign<Props, NewProps>;
|
268 | */
|
269 | export declare type Assign<T extends object, U extends object, I = Diff<T, U> & Intersection<U, T> & Diff<U, T>> = Pick<I, keyof I>;
|
270 | /**
|
271 | * Exact
|
272 | * @desc Create branded object type for exact type matching
|
273 | */
|
274 | export declare type Exact<A extends object> = A & {
|
275 | __brand: keyof A;
|
276 | };
|
277 | /**
|
278 | * Unionize
|
279 | * @desc Disjoin object to form union of objects, each with single property
|
280 | * @example
|
281 | * type Props = { name: string; age: number; visible: boolean };
|
282 | *
|
283 | * // Expect: { name: string; } | { age: number; } | { visible: boolean; }
|
284 | * type UnionizedType = Unionize<Props>;
|
285 | */
|
286 | export declare type Unionize<T extends object> = {
|
287 | [P in keyof T]: {
|
288 | [Q in P]: T[P];
|
289 | };
|
290 | }[keyof T];
|
291 | /**
|
292 | * PromiseType
|
293 | * @desc Obtain Promise resolve type
|
294 | * @example
|
295 | * // Expect: string;
|
296 | * type Response = PromiseType<Promise<string>>;
|
297 | */
|
298 | export declare type PromiseType<T extends Promise<any>> = T extends Promise<infer U> ? U : never;
|
299 | /**
|
300 | * DeepReadonly
|
301 | * @desc Readonly that works for deeply nested structure
|
302 | * @example
|
303 | * // Expect: {
|
304 | * // readonly first: {
|
305 | * // readonly second: {
|
306 | * // readonly name: string;
|
307 | * // };
|
308 | * // };
|
309 | * // }
|
310 | * type NestedProps = {
|
311 | * first: {
|
312 | * second: {
|
313 | * name: string;
|
314 | * };
|
315 | * };
|
316 | * };
|
317 | * type ReadonlyNestedProps = DeepReadonly<NestedProps>;
|
318 | */
|
319 | export declare type DeepReadonly<T> = T extends ((...args: any[]) => any) | Primitive ? T : T extends _DeepReadonlyArray<infer U> ? _DeepReadonlyArray<U> : T extends _DeepReadonlyObject<infer V> ? _DeepReadonlyObject<V> : T;
|
320 | /** @private */
|
321 | export interface _DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {
|
322 | }
|
323 | /** @private */
|
324 | export declare type _DeepReadonlyObject<T> = {
|
325 | readonly [P in keyof T]: DeepReadonly<T[P]>;
|
326 | };
|
327 | /**
|
328 | * DeepRequired
|
329 | * @desc Required that works for deeply nested structure
|
330 | * @example
|
331 | * // Expect: {
|
332 | * // first: {
|
333 | * // second: {
|
334 | * // name: string;
|
335 | * // };
|
336 | * // };
|
337 | * // }
|
338 | * type NestedProps = {
|
339 | * first?: {
|
340 | * second?: {
|
341 | * name?: string;
|
342 | * };
|
343 | * };
|
344 | * };
|
345 | * type RequiredNestedProps = DeepRequired<NestedProps>;
|
346 | */
|
347 | export declare type DeepRequired<T> = T extends (...args: any[]) => any ? T : T extends any[] ? _DeepRequiredArray<T[number]> : T extends object ? _DeepRequiredObject<T> : T;
|
348 | /** @private */
|
349 | export interface _DeepRequiredArray<T> extends Array<DeepRequired<NonUndefined<T>>> {
|
350 | }
|
351 | /** @private */
|
352 | export declare type _DeepRequiredObject<T> = {
|
353 | [P in keyof T]-?: DeepRequired<NonUndefined<T[P]>>;
|
354 | };
|
355 | /**
|
356 | * DeepNonNullable
|
357 | * @desc NonNullable that works for deeply nested structure
|
358 | * @example
|
359 | * // Expect: {
|
360 | * // first: {
|
361 | * // second: {
|
362 | * // name: string;
|
363 | * // };
|
364 | * // };
|
365 | * // }
|
366 | * type NestedProps = {
|
367 | * first?: null | {
|
368 | * second?: null | {
|
369 | * name?: string | null |
|
370 | * undefined;
|
371 | * };
|
372 | * };
|
373 | * };
|
374 | * type RequiredNestedProps = DeepNonNullable<NestedProps>;
|
375 | */
|
376 | export declare type DeepNonNullable<T> = T extends (...args: any[]) => any ? T : T extends any[] ? _DeepNonNullableArray<T[number]> : T extends object ? _DeepNonNullableObject<T> : T;
|
377 | /** @private */
|
378 | export interface _DeepNonNullableArray<T> extends Array<DeepNonNullable<NonNullable<T>>> {
|
379 | }
|
380 | /** @private */
|
381 | export declare type _DeepNonNullableObject<T> = {
|
382 | [P in keyof T]-?: DeepNonNullable<NonNullable<T[P]>>;
|
383 | };
|
384 | /**
|
385 | * DeepPartial
|
386 | * @desc Partial that works for deeply nested structure
|
387 | * @example
|
388 | * // Expect: {
|
389 | * // first?: {
|
390 | * // second?: {
|
391 | * // name?: string;
|
392 | * // };
|
393 | * // };
|
394 | * // }
|
395 | * type NestedProps = {
|
396 | * first: {
|
397 | * second: {
|
398 | * name: string;
|
399 | * };
|
400 | * };
|
401 | * };
|
402 | * type PartialNestedProps = DeepPartial<NestedProps>;
|
403 | */
|
404 | export declare type DeepPartial<T> = {
|
405 | [P in keyof T]?: _DeepPartial<T[P]>;
|
406 | };
|
407 | /** @private */
|
408 | export declare type _DeepPartial<T> = T extends Function ? T : T extends Array<infer U> ? _DeepPartialArray<U> : T extends object ? DeepPartial<T> : T | undefined;
|
409 | /** @private */
|
410 | export interface _DeepPartialArray<T> extends Array<_DeepPartial<T>> {
|
411 | }
|
412 | /**
|
413 | * Brand
|
414 | * @desc Define nominal type of U based on type of T. Similar to Opaque types in Flow.
|
415 | * @example
|
416 | * type USD = Brand<number, "USD">
|
417 | * type EUR = Brand<number, "EUR">
|
418 | *
|
419 | * const tax = 5 as USD;
|
420 | * const usd = 10 as USD;
|
421 | * const eur = 10 as EUR;
|
422 | *
|
423 | * function gross(net: USD): USD {
|
424 | * return (net + tax) as USD;
|
425 | * }
|
426 | *
|
427 | * // Expect: No compile error
|
428 | * gross(usd);
|
429 | * // Expect: Compile error (Type '"EUR"' is not assignable to type '"USD"'.)
|
430 | * gross(eur);
|
431 | */
|
432 | export declare type Brand<T, U> = T & {
|
433 | __brand: U;
|
434 | };
|
435 | /**
|
436 | * Optional
|
437 | * @desc From `T` make a set of properties by key `K` become optional
|
438 | * @example
|
439 | * type Props = {
|
440 | * name: string;
|
441 | * age: number;
|
442 | * visible: boolean;
|
443 | * };
|
444 | *
|
445 | * // Expect: { name?: string; age?: number; visible?: boolean; }
|
446 | * type Props = Optional<Props>;
|
447 | *
|
448 | * // Expect: { name: string; age?: number; visible?: boolean; }
|
449 | * type Props = Optional<Props, 'age' | 'visible'>;
|
450 | */
|
451 | export declare type Optional<T extends object, K extends keyof T = keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
452 | /**
|
453 | * ValuesType
|
454 | * @desc Get the union type of all the values in an object, array or array-like type `T`
|
455 | * @example
|
456 | * type Props = { name: string; age: number; visible: boolean };
|
457 | * // Expect: string | number | boolean
|
458 | * type PropsValues = ValuesType<Props>;
|
459 | *
|
460 | * type NumberArray = number[];
|
461 | * // Expect: number
|
462 | * type NumberItems = ValuesType<NumberArray>;
|
463 | *
|
464 | * type ReadonlySymbolArray = readonly symbol[];
|
465 | * // Expect: symbol
|
466 | * type SymbolItems = ValuesType<ReadonlySymbolArray>;
|
467 | *
|
468 | * type NumberTuple = [1, 2];
|
469 | * // Expect: 1 | 2
|
470 | * type NumberUnion = ValuesType<NumberTuple>;
|
471 | *
|
472 | * type ReadonlyNumberTuple = readonly [1, 2];
|
473 | * // Expect: 1 | 2
|
474 | * type AnotherNumberUnion = ValuesType<NumberTuple>;
|
475 | *
|
476 | * type BinaryArray = Uint8Array;
|
477 | * // Expect: number
|
478 | * type BinaryItems = ValuesType<BinaryArray>;
|
479 | */
|
480 | export declare type ValuesType<T extends ReadonlyArray<any> | ArrayLike<any> | Record<any, any>> = T extends ReadonlyArray<any> ? T[number] : T extends ArrayLike<any> ? T[number] : T extends object ? T[keyof T] : never;
|
481 | /**
|
482 | * Required
|
483 | * @desc From `T` make a set of properties by key `K` become required
|
484 | * @example
|
485 | * type Props = {
|
486 | * name?: string;
|
487 | * age?: number;
|
488 | * visible?: boolean;
|
489 | * };
|
490 | *
|
491 | * // Expect: { name: string; age: number; visible: boolean; }
|
492 | * type Props = Required<Props>;
|
493 | *
|
494 | * // Expect: { name?: string; age: number; visible: boolean; }
|
495 | * type Props = Required<Props, 'age' | 'visible'>;
|
496 | */
|
497 | export declare type AugmentedRequired<T extends object, K extends keyof T = keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
498 | /**
|
499 | * UnionToIntersection
|
500 | * @desc Get intersection type given union type `U`
|
501 | * Credit: jcalz
|
502 | * @see https://stackoverflow.com/a/50375286/7381355
|
503 | * @example
|
504 | * // Expect: { name: string } & { age: number } & { visible: boolean }
|
505 | * UnionToIntersection<{ name: string } | { age: number } | { visible: boolean }>
|
506 | */
|
507 | export declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
508 | /**
|
509 | * Mutable
|
510 | * @desc From `T` make all properties become mutable
|
511 | * @example
|
512 | * type Props = {
|
513 | * readonly name: string;
|
514 | * readonly age: number;
|
515 | * readonly visible: boolean;
|
516 | * };
|
517 | *
|
518 | * // Expect: { name: string; age: number; visible: boolean; }
|
519 | * Mutable<Props>;
|
520 | */
|
521 | export declare type Mutable<T> = {
|
522 | -readonly [P in keyof T]: T[P];
|
523 | };
|
524 | export declare type Writable<T> = Mutable<T>;
|
525 | export {};
|