UNPKG

16.5 kBTypeScriptView Raw
1import { 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 */
21export 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 */
31export type AnyFunction = (...args: any[]) => unknown;
32
33/**
34 * A function taking 0 arguments.
35 * @deprecated Use `() => unknown` instead
36 */
37export type Arity0Fn = () => any;
38
39/**
40 * A function taking 1 argument.
41 * @deprecated Use `(a: any) => unknown` instead
42 */
43export type Arity1Fn = (a: any) => any;
44
45/**
46 * A function taking 2 arguments.
47 * @deprecated Use `(a: any, b: any) => unknown` instead
48 */
49export 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 */
56export interface ArrayLike {
57 nodeType: number;
58}
59
60/**
61 * <needs description>
62 * @param K
63 */
64export 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 */
70export type AtLeastOneFunctionsFlow<TArgs extends any[], TResult> =
71 | [(...args: TArgs) => any, ...Array<(args: any) => any>, (...args: any[]) => TResult]
72 | [(...args: TArgs) => TResult];
73export 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 */
82export interface CharList extends String {
83 push(x: string): void;
84}
85
86/**
87 * R.cond's [predicate, transform] pair.
88 */
89export 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 */
94export 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 */
100export interface Dictionary<A> {
101 [index: string]: A;
102}
103
104/**
105 * Represents all objects evolvable with Evolver E
106 * @param E
107 */
108export 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 */
117export 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 */
125type 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 */
131export 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 */
141type 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 */
152type 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 */
165export type Falsy = undefined | null | 0 | '' | false;
166
167/**
168 * The type of `R.find` and `R.findLast`
169 *
170 * @deprecated Inlined.
171 */
172export 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 */
183export 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 */
192export 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 */
199export 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 */
209type 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 */
229type 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 */
250type 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 */
263type 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 */
286export 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 */
304type 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 */
321export 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 */
337type 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 */
348type 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 */
363export 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 */
384export 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 */
400export 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 */
409export 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 */
414export type Ord = number | string | boolean | Date;
415
416/**
417 * `a` is less than `b`
418 */
419export type LT = -1;
420/**
421 * `a` is equal to `b`
422 */
423export type EQ = 0;
424/**
425 * `a` is greater than `b`
426 */
427export type GT = 1;
428
429/**
430 * Represents two values' order
431 */
432export 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
445export 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 */
454export type Path = ReadonlyArray<number | string>;
455
456/**
457 * A placeholder used to skip parameters, instead adding a parameter to the returned function.
458 */
459export 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 */
472export 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 */
482export 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 */
488export 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 */
496export 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 */
502export 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 */
512export 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 */
525export 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 */
533export 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 */
540export 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 */
555export type Tuple<T, N extends number> = N extends N ? (number extends N ? T[] : _TupleOf<T, N, []>) : never;
556type _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 */
562export 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 */
573export 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
579export {};