UNPKG

17.9 kBTypeScriptView Raw
1import { 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 */
16export 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 */
27export 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 */
35export 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 */
43export 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 */
51export 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 */
68export 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 */
80export 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 */
94export 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];
101export 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 */
113export 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];
120declare 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 */
131export 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 */
144export 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 */
159export 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 */
173export 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 */
185export 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 */
198export 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 */
212export 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 */
225export 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 */
236export 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 */
247export 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 */
258export 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 */
269export 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 */
274export 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 */
286export 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 */
298export 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 */
319export 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 */
321export interface _DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {
322}
323/** @private */
324export 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 */
347export declare type DeepRequired<T> = T extends (...args: any[]) => any ? T : T extends any[] ? _DeepRequiredArray<T[number]> : T extends object ? _DeepRequiredObject<T> : T;
348/** @private */
349export interface _DeepRequiredArray<T> extends Array<DeepRequired<NonUndefined<T>>> {
350}
351/** @private */
352export 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 */
376export declare type DeepNonNullable<T> = T extends (...args: any[]) => any ? T : T extends any[] ? _DeepNonNullableArray<T[number]> : T extends object ? _DeepNonNullableObject<T> : T;
377/** @private */
378export interface _DeepNonNullableArray<T> extends Array<DeepNonNullable<NonNullable<T>>> {
379}
380/** @private */
381export 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 */
404export declare type DeepPartial<T> = {
405 [P in keyof T]?: _DeepPartial<T[P]>;
406};
407/** @private */
408export declare type _DeepPartial<T> = T extends Function ? T : T extends Array<infer U> ? _DeepPartialArray<U> : T extends object ? DeepPartial<T> : T | undefined;
409/** @private */
410export 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 */
432export 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 */
451export 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 */
480export 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 */
497export 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 */
507export 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 */
521export declare type Mutable<T> = {
522 -readonly [P in keyof T]: T[P];
523};
524export declare type Writable<T> = Mutable<T>;
525export {};