import { A, O, T } from "ts-toolbelt"; // /////////////////////////////////////////////////////////////////////////////////////// // TOOLS ///////////////////////////////////////////////////////////////////////////////// // Here lies a loose collection of tools that compute types for the functions in "index.d.ts" // The goal of this file is to keep "index.d.ts" readable as well as hiding implementations // WHEN ADDING A NEW TOOL // - Add documentation for the tool you've created // - Add on your tool's docs // TODO // - Types need proper descriptions, so that we know what they do // --------------------------------------------------------------------------------------- // A /** * */ export type Arity0Fn = () => any; /** * */ export type Arity1Fn = (a: any) => any; /** * */ export type Arity2Fn = (a: any, b: any) => any; /** * */ export interface ArrayLike { nodeType: number; } /** * * @param K */ export interface AssocPartialOne { (val: T): (obj: U) => Record & U; (val: T, obj: U): Record & U; } // --------------------------------------------------------------------------------------- // C /** * */ export interface CharList extends String { push(x: string): void; } /** * * @param V0 * @param R */ export type ComposeWithFns = [ (x0: V0) => R ] | [ (x: any) => R, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: any) => any, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: any) => any, (x: any) => any, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: V0) => any ] | [ (x: any) => R, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: V0) => any ]; // --------------------------------------------------------------------------------------- // D /** * * @param A */ export interface Dictionary { [index: string]: A; } // --------------------------------------------------------------------------------------- // E /** * Represents all objects evolvable with Evolver E * @param E */ export type Evolvable = { [P in keyof E]?: Evolved; }; /** * * @param O * @param E */ export type Evolve, E extends Evolver> = { [P in keyof O]: P extends keyof E ? EvolveValue : O[P]; }; /** * * @param A */ type Evolved = A extends (value: infer V) => any ? V : A extends Evolver ? Evolvable : never; /** * A set of transformation to run as part of an evolve * @param T - the type to be evolved */ export type Evolver = any> = { // if T[K] isn't evolvable, don't allow nesting for that property [key in keyof Partial]: ((value: T[key]) => T[key]) | (T[key] extends Evolvable ? Evolver : never); }; /** * * @param O * @param E */ type EvolveNestedValue = O extends object ? O extends Evolvable ? Evolve : never : never; /** * * @param V * @param E */ type EvolveValue = E extends (value: V) => any ? ReturnType : E extends Evolver ? EvolveNestedValue : never; // --------------------------------------------------------------------------------------- // F /** * */ export interface Filter { (fn: (value: T) => boolean): FilterOnceApplied; (fn: (value: T) => boolean): (list: readonly T[]) => T[]; (fn: (value: T) => boolean): (list: Dictionary) => Dictionary; (fn: (value: T) => boolean, list: readonly T[]): T[]; (fn: (value: T) => boolean, obj: Dictionary): Dictionary; } /** * * @param A */ type FilterOnceApplied = >(source: K) => K extends Array ? U[] : K extends Dictionary ? Dictionary : never; /** * * @param A */ export interface Functor { map(fn: (a: A) => U): Functor; } // --------------------------------------------------------------------------------------- // K /** * * @param K * @param V */ export type KeyValuePair = [K, V]; // --------------------------------------------------------------------------------------- // L /** * */ export interface Lens { (obj: T): U; set(str: string, obj: T): U; } // --------------------------------------------------------------------------------------- // M /** * Merge an object `O1` with `O2` * @param O1 * @param O2 * @param Depth * * `O1` & `O2` are intersected with `[]` so that we can * handle the scenario where we merge arrays (like ramda). * Ramda removes array props when merging arrays, and thus * only keeps own properties. This is what `ObjectOf` does. * * => ramda's `merge` functions are 100% properly typed. * * */ export type Merge = O.MergeUp, T.ObjectOf, Depth>; /** * Merge multiple objects `Os` with each other * @param Os * * It essentially works like [[Merge]], since the utility * `MergeUp` is used by `AssignUp` internally. * * */ export type MergeAll = O.AssignUp<{}, Os> extends infer M ? {} extends M // nothing merged => bcs no `as const` ? T.UnionOf // so we output the approximate types : T.ObjectOf // otherwise, we can get accurate types : never; // --------------------------------------------------------------------------------------- // O /** * */ export type ObjPred = (value: any, key: string) => boolean; /** * */ export type Ord = number | string | boolean | Date; // --------------------------------------------------------------------------------------- // P /** * */ export type Path = Array<(number | string)>; /** * */ export type Placeholder = A.x & {'@@functional/placeholder': true}; /** * */ export type Pred = (...a: readonly any[]) => boolean; /** * * @param V0 * @param R */ export type PipeWithFns = [ (x0: V0) => R ] | [ (x0: V0) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => R ] | [ (x0: V0) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => any, (x: any) => R ]; // --------------------------------------------------------------------------------------- // R /** * * @param A */ export interface Reduced { '@@transducer/value': A; '@@transducer/reduced': true; } // --------------------------------------------------------------------------------------- // S /** * * @param A */ export type SafePred = (...a: readonly A[]) => boolean; // --------------------------------------------------------------------------------------- // V /** * * @param R */ export type ValueOfRecord = R extends Record ? T : never; export {};