1 | import { A, M, O, T } from 'ts-toolbelt';
|
2 |
|
3 | // Here lies a loose collection of tools that compute types for the functions in "index.d.ts"
|
4 | // The goal of this file is to keep "index.d.ts" readable as well as hiding implementations
|
5 |
|
6 | // WHEN ADDING A NEW TOOL
|
7 | // - Add documentation for the tool you've created
|
8 | // - Add <created by @username> on your tool's docs
|
9 |
|
10 | // TODO
|
11 | // - Types need proper descriptions, so that we know what they do
|
12 |
|
13 | /**
|
14 | * A type that any constructor is assignable to.
|
15 | * Use as a generic constraint (`T extends AnyConstructor`)
|
16 | * and for function parameters (`a: AnyConstructor`).
|
17 | * Use `new (...args: unknown[]) => unknown` instead for function return types.
|
18 | *
|
19 | * <created by @somebody1234>
|
20 | */
|
21 | export type AnyConstructor = new (...args: any[]) => unknown;
|
22 |
|
23 | /**
|
24 | * A type that any function is assignable to.
|
25 | * Use as a generic constraint (`T extends AnyFunction`)
|
26 | * and for function parameters (`a: AnyFunction`).
|
27 | * Use `(...args: unknown[]) => unknown` instead for function return types.
|
28 | *
|
29 | * <created by @somebody1234>
|
30 | */
|
31 | export type AnyFunction = (...args: any[]) => unknown;
|
32 |
|
33 | /**
|
34 | * A function taking 0 arguments.
|
35 | * @deprecated Use `() => unknown` instead
|
36 | */
|
37 | export type Arity0Fn = () => any;
|
38 |
|
39 | /**
|
40 | * A function taking 1 argument.
|
41 | * @deprecated Use `(a: any) => unknown` instead
|
42 | */
|
43 | export type Arity1Fn = (a: any) => any;
|
44 |
|
45 | /**
|
46 | * A function taking 2 arguments.
|
47 | * @deprecated Use `(a: any, b: any) => unknown` instead
|
48 | */
|
49 | export type Arity2Fn = (a: any, b: any) => any;
|
50 |
|
51 | /**
|
52 | * <needs description>
|
53 | *
|
54 | * @deprecated Unknown purpose. If really needed, consider `{ nodeType: number; }` instead.
|
55 | */
|
56 | export interface ArrayLike {
|
57 | nodeType: number;
|
58 | }
|
59 |
|
60 | /**
|
61 | * <needs description>
|
62 | * @param K
|
63 | */
|
64 | export type AssocPartialOne<K extends keyof any> = (<T>(val: T) => <U>(obj: U) => Record<K, T> & Omit<U, K>) &
|
65 | (<T, U>(val: T, obj: U) => Record<K, T> & Omit<U, K>);
|
66 |
|
67 | /**
|
68 | * Array of functions to compose/pipe with.
|
69 | */
|
70 | export type AtLeastOneFunctionsFlow<TArgs extends any[], TResult> =
|
71 | | [(...args: TArgs) => any, ...Array<(args: any) => any>, (...args: any[]) => TResult]
|
72 | | [(...args: TArgs) => TResult];
|
73 | export type AtLeastOneFunctionsFlowFromRightToLeft<TArgs extends any[], TResult> =
|
74 | | [(...args: any) => TResult, ...Array<(args: any) => any>, (...args: TArgs) => any]
|
75 | | [(...args: TArgs) => TResult];
|
76 |
|
77 | /**
|
78 | * <needs description>
|
79 | *
|
80 | * @deprecated Unknown purpose. If really needed, consider `string & { push(x: string): void; }` instead.
|
81 | */
|
82 | export interface CharList extends String {
|
83 | push(x: string): void;
|
84 | }
|
85 |
|
86 | /**
|
87 | * R.cond's [predicate, transform] pair.
|
88 | */
|
89 | export type CondPair<T extends any[], R> = [(...val: T) => boolean, (...val: T) => R];
|
90 |
|
91 | /**
|
92 | * R.cond's [predicate, transform] pair in a typeguarded version
|
93 | */
|
94 | export type CondPairTypeguard<T, TFiltered extends T, R> = [(value: T) => value is TFiltered, (value: TFiltered) => R];
|
95 |
|
96 | /**
|
97 | * Dictionary
|
98 | * @param A The type of dictionary values
|
99 | */
|
100 | export interface Dictionary<A> {
|
101 | [index: string]: A;
|
102 | }
|
103 |
|
104 | /**
|
105 | * Represents all objects evolvable with Evolver E
|
106 | * @param E
|
107 | */
|
108 | export type Evolvable<E extends Evolver> = {
|
109 | [P in keyof E]?: Evolved<E[P]>;
|
110 | };
|
111 |
|
112 | /**
|
113 | * <needs description>
|
114 | * @param O
|
115 | * @param E
|
116 | */
|
117 | export type Evolve<O extends Evolvable<E>, E extends Evolver> = {
|
118 | [P in keyof O]: P extends keyof E ? EvolveValue<O[P], E[P]> : O[P];
|
119 | };
|
120 |
|
121 | /**
|
122 | * <needs description>
|
123 | * @param A
|
124 | */
|
125 | type Evolved<A> = A extends (value: infer V) => any ? V : A extends Evolver ? Evolvable<A> : never;
|
126 |
|
127 | /**
|
128 | * A set of transformation to run as part of an evolve
|
129 | * @param T - the type to be evolved
|
130 | */
|
131 | export type Evolver<T extends Evolvable<any> = any> = {
|
132 | // if T[K] isn't evolvable, don't allow nesting for that property
|
133 | [key in keyof Partial<T>]: ((value: T[key]) => T[key]) | (T[key] extends Evolvable<any> ? Evolver<T[key]> : never);
|
134 | };
|
135 |
|
136 | /**
|
137 | * <needs description>
|
138 | * @param O
|
139 | * @param E
|
140 | */
|
141 | type EvolveNestedValue<O, E extends Evolver> = O extends object
|
142 | ? O extends Evolvable<E>
|
143 | ? Evolve<O, E>
|
144 | : never
|
145 | : never;
|
146 |
|
147 | /**
|
148 | * <needs description>
|
149 | * @param V
|
150 | * @param E
|
151 | */
|
152 | type EvolveValue<V, E> = E extends (value: V) => any
|
153 | ? ReturnType<E>
|
154 | : E extends Evolver
|
155 | ? EvolveNestedValue<V, E>
|
156 | : never;
|
157 |
|
158 | /**
|
159 | * All falsy JavaScript values representable by the type system.
|
160 | *
|
161 | * @note Actually there are six (seven) falsy values in JS - the sixth being `NaN`;
|
162 | * the seventh being `document.all`. However `NaN` is not a valid literal type,
|
163 | * and `document.all` is an object so it's probably not a good idea to add it either.
|
164 | */
|
165 | export type Falsy = undefined | null | 0 | '' | false;
|
166 |
|
167 | /**
|
168 | * The type of `R.find` and `R.findLast`
|
169 | *
|
170 | * @deprecated Inlined.
|
171 | */
|
172 | export interface Find {
|
173 | <T, P extends T>(pred: (val: T) => val is P, list: readonly T[]): P | undefined;
|
174 | <T>(pred: (val: T) => boolean, list: readonly T[]): T | undefined;
|
175 | <T, P extends T>(pred: (val: T) => val is P): (list: readonly T[]) => P | undefined;
|
176 | <T>(pred: (val: T) => boolean): (list: readonly T[]) => T | undefined;
|
177 | }
|
178 |
|
179 | /**
|
180 | * A functor satisfying the FantasyLand spec
|
181 | * @param A
|
182 | */
|
183 | export type Functor<A> =
|
184 | | { ['fantasy-land/map']: <B>(fn: (a: A) => B) => Functor<B>; [key: string]: any }
|
185 | | { map: <B>(fn: (a: A) => B) => Functor<B>; [key: string]: any };
|
186 |
|
187 | /**
|
188 | * A pair containing the key and corresponding value of an object.
|
189 | * @param K Key type
|
190 | * @param V Value type
|
191 | */
|
192 | export type KeyValuePair<K, V> = [K, V];
|
193 |
|
194 | /**
|
195 | * <needs description>
|
196 | * @param S Type of the full object
|
197 | * @param A Type of the lens focus
|
198 | */
|
199 | export type Lens<S, A> = (functorFactory: (a: A) => Functor<A>) => (s: S) => Functor<S>;
|
200 |
|
201 | /**
|
202 | * Returns true if T1 array length less than or equal to length of array T2, else returns false
|
203 | *
|
204 | * @param T1 First readonly array
|
205 | * @param T2 Second readonly array
|
206 | *
|
207 | * <created by @valerii15298>
|
208 | */
|
209 | type Arr1LessThanOrEqual<
|
210 | T1 extends ReadonlyArray<any>,
|
211 | T2 extends ReadonlyArray<any>,
|
212 | > = T1['length'] extends T2['length']
|
213 | ? true
|
214 | : T2['length'] extends 0
|
215 | ? false
|
216 | : T2 extends readonly [infer First, ...infer Rest]
|
217 | ? Arr1LessThanOrEqual<T1, Rest>
|
218 | : never;
|
219 |
|
220 | /**
|
221 | * Return true if types T1 and T2 can intersect, e.g. both are primitives or both are objects.
|
222 | * Taking into account branded types too.
|
223 | *
|
224 | * @param T1 First readonly array
|
225 | * @param T2 Second readonly array
|
226 | *
|
227 | * <created by @valerii15298>
|
228 | */
|
229 | type Intersectable<T1, T2> = [T1] extends [T2]
|
230 | ? true
|
231 | : [T2] extends [T1]
|
232 | ? true
|
233 | : [T1] extends [object]
|
234 | ? [T2] extends [object]
|
235 | ? true
|
236 | : false
|
237 | : [T1] extends [M.Primitive]
|
238 | ? [T2] extends [M.Primitive]
|
239 | ? true
|
240 | : false
|
241 | : false;
|
242 |
|
243 | /**
|
244 | * Check if type `T` is `any`
|
245 | *
|
246 | * @param T Type to check
|
247 | *
|
248 | * <created by @valerii15298>
|
249 | */
|
250 | type IsAny<T> = 0 extends 1 & T ? true : false;
|
251 |
|
252 | /**
|
253 | * Intersection when produced result can be usable type.
|
254 | * For example type `{a: any} & number` will not be reduced to `never`
|
255 | * but `Intersection<{a: any}, number>` will be `never`
|
256 | * If one of type is any, another type will be returned.
|
257 | *
|
258 | * @param T1
|
259 | * @param T2
|
260 | *
|
261 | * <created by @valerii15298>
|
262 | */
|
263 | type Intersection<T1, T2> = Intersectable<T1, T2> extends true
|
264 | ? IsAny<T1> extends true
|
265 | ? T2
|
266 | : IsAny<T2> extends true
|
267 | ? T1
|
268 | : T1 & T2
|
269 | : never;
|
270 |
|
271 | /**
|
272 | * Merge second array with first one,
|
273 | * resulting array will have the same length as array T1,
|
274 | * every item in new array will be item from first array(T1) by corresponding index
|
275 | * intersected with item from second array(also with the same index) if such exist
|
276 | *
|
277 | * examples:
|
278 | * `mergeArrWithLeft<[1, number, number, string], [number, 2, 7]>` => `[1, 2, 7, string]`
|
279 | * `mergeArrWithLeft<[1, string], [number, "exact text", number, any]>` => `[1, "exact text"]`
|
280 | *
|
281 | * @param T1
|
282 | * @param T2
|
283 | *
|
284 | * <created by @valerii15298>
|
285 | */
|
286 | export type mergeArrWithLeft<T1 extends ReadonlyArray<any>, T2 extends ReadonlyArray<any>> = readonly [
|
287 | ...{
|
288 | readonly [Index in keyof T1]: Index extends keyof T2 ? Intersection<T1[Index], T2[Index]> : T1[Index];
|
289 | },
|
290 | ];
|
291 |
|
292 | /**
|
293 | * The same as mergeArrWithLeft but will merge smaller array to larger one,
|
294 | * so that data will not be lost and maximum length array will be returned
|
295 | *
|
296 | * example: MergeArrays<[1, number], [number, 2, string]>
|
297 | * will result to => [1, 2, string]
|
298 | *
|
299 | * @param T1
|
300 | * @param T2
|
301 | *
|
302 | * <created by @valerii15298>
|
303 | */
|
304 | type MergeArrays<T1 extends ReadonlyArray<any>, T2 extends ReadonlyArray<any>> = Arr1LessThanOrEqual<
|
305 | T1,
|
306 | T2
|
307 | > extends true
|
308 | ? mergeArrWithLeft<T2, T1>
|
309 | : mergeArrWithLeft<T1, T2>;
|
310 |
|
311 | /**
|
312 | * Given array of functions will return new array which will be constructed
|
313 | * merging all functions parameters array using mergeArrays generic.
|
314 | *
|
315 | * If provided array is not array of functions, return type will be empty array([])
|
316 | *
|
317 | * @param T Array of functions
|
318 | *
|
319 | * <created by @valerii15298>
|
320 | */
|
321 | export type LargestArgumentsList<T extends ReadonlyArray<any>> = T extends readonly [
|
322 | (...args: infer Args) => any,
|
323 | ...infer Rest,
|
324 | ]
|
325 | ? MergeArrays<LargestArgumentsList<Rest>, Args>
|
326 | : readonly [];
|
327 |
|
328 | /**
|
329 | * Checks if type is `never`
|
330 | *
|
331 | * Returns `true` if type is `never`, else returns `false`
|
332 | *
|
333 | * @param T Type to check
|
334 | *
|
335 | * <created by @valerii15298>
|
336 | */
|
337 | type IsNever<T> = [T] extends [never] ? true : false;
|
338 |
|
339 | /**
|
340 | * Checks if array of types is contains `never` type
|
341 | *
|
342 | * Returns `true` if array contains `never` type, else returns `false`
|
343 | *
|
344 | * @param T Array of types to check
|
345 | *
|
346 | * <created by @valerii15298>
|
347 | */
|
348 | type HasNever<T extends readonly any[]> = T extends readonly [infer First, ...infer Rest]
|
349 | ? IsNever<First> extends true
|
350 | ? true
|
351 | : HasNever<Rest>
|
352 | : false;
|
353 |
|
354 | /**
|
355 | * Checks if corresponding types of arguments in functions overlap(have at least one type in common, except never)
|
356 | *
|
357 | * Returns `unknown` if arguments types overlap, else returns `ErrorMsg`
|
358 | *
|
359 | * @param T Type to check
|
360 | *
|
361 | * <created by @valerii15298>
|
362 | */
|
363 | export type IfFunctionsArgumentsDoNotOverlap<T extends ReadonlyArray<Fn>, ErrorMsg extends string> = HasNever<
|
364 | LargestArgumentsList<T>
|
365 | > extends true
|
366 | ? ErrorMsg
|
367 | : unknown;
|
368 |
|
369 | /**
|
370 | * Merge an object `O1` with `O2`
|
371 | * @param O1
|
372 | * @param O2
|
373 | * @param Depth
|
374 | *
|
375 | * `O1` & `O2` are intersected with `[]` so that we can
|
376 | * handle the scenario where we merge arrays (like ramda).
|
377 | * Ramda removes array props when merging arrays, and thus
|
378 | * only keeps own properties. This is what `ObjectOf` does.
|
379 | *
|
380 | * => ramda's `merge` functions are 100% properly typed.
|
381 | *
|
382 | * <created by @pirix-gh>
|
383 | */
|
384 | export type Merge<O1 extends object, O2 extends object, Depth extends 'flat' | 'deep'> = O.MergeUp<
|
385 | T.ObjectOf<O1>,
|
386 | T.ObjectOf<O2>,
|
387 | Depth,
|
388 | 1
|
389 | >;
|
390 |
|
391 | /**
|
392 | * Merge multiple objects `Os` with each other
|
393 | * @param Os
|
394 | *
|
395 | * It essentially works like [[Merge]], since the utility
|
396 | * `MergeUp` is used by `AssignUp` internally.
|
397 | *
|
398 | * <created by @pirix-gh>
|
399 | */
|
400 | export type MergeAll<Os extends readonly object[]> = O.AssignUp<{}, Os, 'flat', 1> extends infer M
|
401 | ? {} extends M // nothing merged => bcs no `as const`
|
402 | ? T.UnionOf<Os> // so we output the approximate types
|
403 | : M // otherwise, we can get accurate types
|
404 | : never;
|
405 |
|
406 | /**
|
407 | * Predicate for an object containing the key.
|
408 | */
|
409 | export type ObjPred<T = unknown> = (value: any, key: unknown extends T ? string : keyof T) => boolean;
|
410 |
|
411 | /**
|
412 | * Values that can be compared using the relational operators `<`/`<=`/`>`/`>=`
|
413 | */
|
414 | export type Ord = number | string | boolean | Date;
|
415 |
|
416 | /**
|
417 | * `a` is less than `b`
|
418 | */
|
419 | export type LT = -1;
|
420 | /**
|
421 | * `a` is equal to `b`
|
422 | */
|
423 | export type EQ = 0;
|
424 | /**
|
425 | * `a` is greater than `b`
|
426 | */
|
427 | export type GT = 1;
|
428 |
|
429 | /**
|
430 | * Represents two values' order
|
431 | */
|
432 | export type Ordering = LT | EQ | GT;
|
433 |
|
434 | /**
|
435 | * An object with at least one of its properties beeing of type `Key`.
|
436 | *
|
437 | * @example
|
438 | * ```
|
439 | * // $ExpectType { foo: unknown } | { bar: unknown }
|
440 | * type Foo = ObjectHavingSome<"foo" | "bar">
|
441 | * ```
|
442 | */
|
443 | // Implementation taken from
|
444 | // https://github.com/piotrwitek/utility-types/blob/df2502ef504c4ba8bd9de81a45baef112b7921d0/src/mapped-types.ts#L351-L362
|
445 | export type ObjectHavingSome<Key extends string> = A.Clean<
|
446 | {
|
447 | [K in Key]: { [P in K]: unknown };
|
448 | }[Key]
|
449 | >;
|
450 |
|
451 | /**
|
452 | * <needs description>
|
453 | */
|
454 | export type Path = ReadonlyArray<number | string>;
|
455 |
|
456 | /**
|
457 | * A placeholder used to skip parameters, instead adding a parameter to the returned function.
|
458 | */
|
459 | export type Placeholder = A.x & { '@@functional/placeholder': true };
|
460 |
|
461 | /**
|
462 | * Takes a lists of arguments and returns either `true` or `false`.
|
463 | *
|
464 | * Classical predicates only take one argument, but since ramda
|
465 | * supports multiple arguments, we also use them like that.
|
466 | *
|
467 | * Note that these predicates, don't represent typeguards,
|
468 | * meaning when this type is used, we can't get type narrowing.
|
469 | *
|
470 | * @see {@link PredTypeguard} for the typeguard version of this.
|
471 | */
|
472 | export type Pred<T extends any[] = any[]> = (...a: T) => boolean;
|
473 |
|
474 | /**
|
475 | * Takes an argument and returns either `true` or `false`.
|
476 | *
|
477 | * This is usually used as an overload before {@link Pred}.
|
478 | * If you would this type alone, the function would **required**
|
479 | * to be a typeguard, meaning a simple function just returning
|
480 | * a `boolean` wouldn't satisfy this constrain.
|
481 | */
|
482 | export type PredTypeguard<T, TTypeguarded extends T> = (a: T) => a is TTypeguarded;
|
483 |
|
484 | /**
|
485 | * A runtime-branded value used to stop `reduce` and `transduce` early.
|
486 | * @param A The type of the contained value
|
487 | */
|
488 | export interface Reduced<A> {
|
489 | '@@transducer/value': A;
|
490 | '@@transducer/reduced': true;
|
491 | }
|
492 |
|
493 | /**
|
494 | * A type representing any function. Useful as a generic constraint.
|
495 | */
|
496 | export type Fn = (...args: any[]) => unknown;
|
497 |
|
498 | /**
|
499 | * Converts an array of functions to an array of their return types.
|
500 | * @param A The array of functions
|
501 | */
|
502 | export type ReturnTypesOfFns<A extends ReadonlyArray<Fn>> = A extends readonly [(...args: any[]) => infer H, ...infer R]
|
503 | ? R extends readonly Fn[]
|
504 | ? readonly [H, ...ReturnTypesOfFns<R>]
|
505 | : readonly []
|
506 | : readonly [];
|
507 |
|
508 | /**
|
509 | * Converts an array of functions taking a single parameter to an array of their parameter types.
|
510 | * @param A The array of functions
|
511 | */
|
512 | export type InputTypesOfFns<A extends ReadonlyArray<Fn>> = A extends [infer H, ...infer R]
|
513 | ? H extends Fn
|
514 | ? R extends Fn[]
|
515 | ? [Parameters<H>[0], ...InputTypesOfFns<R>]
|
516 | : []
|
517 | : []
|
518 | : [];
|
519 |
|
520 | /**
|
521 | * The type of the values of a record.
|
522 | * @param R The record.
|
523 | * @deprecated Use `T[keyof T]` instead.
|
524 | */
|
525 | export type ValueOfRecord<R> = R extends Record<any, infer T> ? T : never;
|
526 |
|
527 | /**
|
528 | * If `T` is a union, `T[keyof T]` (cf. `map` and `values` in `index.d.ts`) contains the types of object values that are common across the union (i.e., an intersection).
|
529 | * Because we want to include the types of all values, including those that occur in some, but not all members of the union, we first define `ValueOfUnion`.
|
530 | * @see https://stackoverflow.com/a/60085683
|
531 | * @param T The (possible) union
|
532 | */
|
533 | export type ValueOfUnion<T> = T extends infer U ? U[keyof U] : never;
|
534 |
|
535 | /**
|
536 | * Take first `N` types of an Tuple
|
537 | * @param N Length of prefix to take
|
538 | * @param Tuple Input tuple type
|
539 | */
|
540 | export type Take<
|
541 | N extends number,
|
542 | Tuple extends any[],
|
543 | ReturnTuple extends any[] = [],
|
544 | > = ReturnTuple['length'] extends N
|
545 | ? ReturnTuple
|
546 | : Tuple extends [infer X, ...infer Xs]
|
547 | ? Take<N, Xs, [...ReturnTuple, X]>
|
548 | : never;
|
549 |
|
550 | /**
|
551 | * A homogeneous tuple of length `N`.
|
552 | * @param T Type of every element of the tuple
|
553 | * @param N Length of the tuple
|
554 | */
|
555 | export type Tuple<T, N extends number> = N extends N ? (number extends N ? T[] : _TupleOf<T, N, []>) : never;
|
556 | type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>;
|
557 |
|
558 | /**
|
559 | * Map tuple of ordinary type to tuple of array type
|
560 | * [string, number] -> [string[], number[]]
|
561 | */
|
562 | export type ToTupleOfArray<Tuple extends any[]> = Tuple extends []
|
563 | ? []
|
564 | : Tuple extends [infer X, ...infer Xs]
|
565 | ? [X[], ...ToTupleOfArray<Xs>]
|
566 | : never;
|
567 |
|
568 | /**
|
569 | * Map tuple of ordinary type to tuple of function type
|
570 | * @param R Parameter type of every function
|
571 | * @param Tuple Return type of every function
|
572 | */
|
573 | export type ToTupleOfFunction<R, Tuple extends any[]> = Tuple extends []
|
574 | ? []
|
575 | : Tuple extends [infer X, ...infer Xs]
|
576 | ? [(arg: R) => X, ...ToTupleOfFunction<R, Xs>]
|
577 | : never;
|
578 |
|
579 | export {};
|