// Minimum TypeScript Version: 3.4 // prettier-ignore export type Functor = F extends A[] ? B[] : F extends { [key: string]: A } ? { [key: string]: B } : F extends Set ? Set : F extends Map ? Map : F extends Promise ? Promise : never; // prettier-ignore export type Unpack = F extends Array ? A : F extends Set ? A : F extends Map ? A : F extends Promise ? A : F extends { [n: string]: infer A } ? A : F extends { [n: number]: infer A } ? A : F extends Record ? A : F extends Record ? A : F extends Record ? A : never; export type HasKey = | { [_ in K]: V } | { [_ in K]?: V | undefined }; export interface ErrorCannotLensIntoOptionalKey { error: 'You have tried to lens through an optional key. Consider using `fill` to provide defaults to your object'; _val: T; _key: K; } // prettier-ignore export type KeyAt = [T] extends [undefined] ? undefined: [T] extends [null] ? null : [T] extends [{ [_ in K]: any }] ? T[K] : [T] extends [{ [_ in K]?: any }] ? T[K] : ErrorCannotLensIntoOptionalKey; export type Collection = | V[] | { [key: string]: V } | Map | Set; export type Container = Collection | Promise; export type Indexable = V[] | Map; export type Index = C extends Indexable ? V : never; export type InputType = F extends (arg: infer A) => Return ? A : never; export type HasPattern = { [K in keyof Pattern]: | Pattern[K] | InputType | (Pattern[K] extends (a: any) => any ? never : HasPattern) }; export type FillingPattern = { [K in keyof Pattern]?: Pattern[K] | FillingPattern }; export type Fill, P> = { [K in Exclude]: T[K] } & { [K in keyof P]: P[K] }; export type Fn0 = () => Out; export type Fn1 = (a: A) => Out; export type Fn2 = (a: A, b: B) => Out; export type Fn3 = (a: A, b: B, c: C) => Out; export type Fn4 = (a: A, b: B, c: C, d: D) => Out; export type Fn5 = (a: A, b: B, c: C, d: D, e: E) => Out; export type Fn6 = ( a: A, b: B, c: C, d: D, e: E, f: F ) => Out; export type Fn7 = ( a: A, b: B, c: C, d: D, e: E, f: F, g: G ) => Out; export type Fn8 = ( a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H ) => Out; export interface Traversal { get(s: Collection): Collection; mod(f: (a: Item) => Item): (s: Collection) => Collection; traversal?: true; } export interface Lens { get(s: S): A; mod(f: (a: A) => A): (s: S) => S; traversal?: false; }