/** @module helper-types.ts */ // import {IsFinite} from 'typescript-tuple' export enum adtn { ap = 'babakness/ap', map = 'babakness/map', chain = 'babakness/chain', flatMap = 'babakness/flatMap', } Array.prototype[ adtn.chain ] = function( fn ) { return this.reduce( ( acc, item ) => acc.concat( fn( item ) ) , [] ) } Array.prototype[ adtn.ap ] = function( arr ) { // Apply return arr[ adtn.chain ]( ( fn ) => this.map( fn ) ) } Array.of = ( val ) => [ val ] declare global { interface ArrayConstructor { _URI: 'Array' } interface Array { [ adtn.ap ]: ( a: any ) => U[], of: T[], } } export type EntryKeyValue = A extends [infer KEY, infer VALUE] ? [KEY, VALUE] : undefined export type EntryKey = A extends [infer KEY, infer VALUE] ? KEY : undefined export type EntryValue = A extends [infer KEY, infer VALUE] ? VALUE : undefined // Types used in project export type Flat = number|string|symbol export type Pairs = Array<[A, B]> export interface Obj { [k: string]: T } export type Predicate = ( x: A ) => boolean export type Predicate2 = ( x: A, y: B ) => boolean export type Complement = Exclude extends never ? boolean : Exclude export type FlattenArray = T extends any[][] ? T[number] : T export type Omit = T extends any ? Pick> : never export type Optional = T extends any ? Omit & {[P in K]?: T[K]} : never // export type valueof = G[I] export type ValueAt = G[ I ] export type ValueOf = T[ Exclude ] export type KeyOf = Exclude export type KeyTypes = string | number | symbol export type Unpacked = T extends Array ? U : // tslint:disable-next-line:no-shadowed-variable T extends ( ...args: any[] ) => infer U ? U : // tslint:disable-next-line:no-shadowed-variable T extends Promise ? U : T export type Function1 = ( a: A ) => B export type Function2 = ( a: A, b: B ) => C export type Function3 = ( a: A, b: B, c: C ) => D export type Function4 = ( a: A, b: B, c: C, d: D ) => E export type Function5 = ( a: A, b: B, c: C, d: D, e: E ) => F export type Function6 = ( a: A, b: B, c: C, d: D, e: E, f: F ) => G export type Function7 = ( a: A, b: B, c: C, d: D, e: E, f: F, g: G ) => H export type Function8 = ( a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H ) => I export type Function9 = ( a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I ) => J export type FunctionV = ( ...a: A[] ) => B export type Function_21 = ( a: A, b: B ) => ( c: C ) => D // export type Function_12 = (a: A) => (b: B, c: C) => D export type Function_211 = ( a: A, b: B ) => ( c: C ) => ( d: D ) => E export type Function_22 = ( a: A, b: B ) => ( c: C, d: D ) => E export type Function_31 = ( a: A, b: B, c: C ) => ( d: D ) => E // export type Function_22 = (a: A, b: B) => (c: C, d: D) => E // export type Function_121 = (a: A) => ( b: B, c: C) => (d: D) => E // export type Function_112 = (a: A) => ( b: B ) => (d: D) => E // export type Function_13 = (a: A) => (b: B, c: C, d: D) => E export type Function_2111 = ( a: A, b: B ) => ( c: C ) => ( d: D ) => ( e: E ) => F export type Function_311 = ( a: A, b: B, c: C ) => ( d: D ) => ( e: E ) => F export type Function_41 = ( a: A, b: B, c: C, d: D ) => ( e: E ) => F export type Function_51 = ( a: A, b: B, c: C, d: D, e: E ) => ( f: F ) => G export type Function_61 = ( a: A, b: B, c: C, d: D, e: E, f: F ) => ( g: G ) => H export type Curried1 = ( a: A ) => B export type Curried2 = ( a: A ) => ( b: B ) => C export type Curried3 = ( a: A ) => ( b: B ) => ( c: C ) => D export type Curried4 = ( a: A ) => ( b: B ) => ( c: C ) => ( d: D ) => E export type Curried5 = ( a: A ) => ( b: B ) => ( c: C ) => ( d: D ) => ( e: E ) => F export type Curried6 = ( a: A ) => ( b: B ) => ( c: C ) => ( d: D ) => ( e: E ) => ( f: F ) => G export type Curried7 = ( a: A ) => ( b: B ) => ( c: C ) => ( d: D ) => ( e: E ) => ( f: F ) => ( g: G ) => H export type Curried8 = ( a: A ) => ( b: B ) => ( c: C ) => ( d: D ) => ( e: E ) => ( f: F ) => ( g: G ) => ( h: H ) => I export type Curried9 = ( a: A ) => ( b: B ) => ( c: C ) => ( d: D ) => ( e: E ) => ( f: F ) => ( g: G ) => ( h: H ) => ( i: I ) => J export interface Functor { map( fn: Function1 ): Functor } export interface Apply extends Functor { ap( fn: Apply< ( a: A ) => B> ): Apply } export interface ArrayApply extends Functor { [ adtn.ap ]( fn: Apply< ( a: A ) => B> ): ArrayApply } export interface Applicative { of( val: A ): Apply } export interface Applicative { of( val: A ): Apply } export interface ArrayApplicative { _URI: F of( val: A ): ArrayApply } export interface Filterable { filter( fn: Predicate ): Filterable } export interface HKT0 { readonly _URI: F } export interface Pushable { readonly concat: ( item: A ) => Pushable } export interface Concattable { readonly concat: ( item: A ) => Concattable } export interface Curried { ( b: B , a: A ): Z ( b: B ): ( a: A ) => Z } // export type AnyFunction = ( ...a: any[] ) => any export type FunctionPropertyNames = { [K in keyof T]: T[K] extends AnyFunction ? K : never }[keyof T] export type FunctionProperties = Pick> export type ObjectPropertyNamesByType = { [K in keyof O]: O[K] extends T ? K : never }[keyof O] export type ObjectPropertiesByType = Pick> export type ToTuple = T extends any[] ? T : any[] // export type Last = utils.Last // export type Head = Tuple extends [ infer H, ...any[] ] ? H : never // export type Head = ValueAt // export type Prepend = utils.Prepend // export type Unshift = utils.Prepend // export type Append = utils.Reverse, Addend>> // export type Push = utils.Reverse, Addend>> // /** // * Concat two tuple into one // * @example `Concat<[0, 1, 2], ['a', 'b', 'c']>` → `[0, 1, 2, 'a', 'b', 'c']` // */ // export type Concat = utils.Concat // /** // * Concat multiple tuples // * @example `ConcatMultiple<[], [0], [1, 2], [3, 4, 5]>` → `[0, 1, 2, 3, 4, 5]` // */ // export type ConcatMultiple = utils.ConcatMultiple // type AnyArray = {[k in number]: any} type AnyArray = any[] export type Prepend = ( ( _: Addend, ..._1: Tuple ) => any ) extends ( ( ..._: infer Result ) => any ) ? Result : never export type Last = { 'empty': Default, 'single': Tuple extends [infer SoleElement] ? SoleElement : never, 'multi': ( ( ..._: Tuple ) => any ) extends ( ( _: any, ..._1: infer Next ) => any ) ? Last : Default, 'infinite': Tuple extends Array ? Element : never, }[ Tuple extends [] ? 'empty' : Tuple extends [any] ? 'single' : Tuple extends Array ? Element[] extends Tuple ? 'infinite' : 'multi' : never ] export type Reverse = { 'empty': Prefix, 'nonEmpty': ( ( ..._: Tuple ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? Reverse> : never, 'infinite': { ERROR: 'xCannot reverse an infinite tuple', CODENAME: 'InfiniteTuple', }, }[ Tuple extends [any, ...any[]] ? IsFinite : 'empty' ] export type IsFinite = { empty: Finite, nonEmpty: ( ( ..._: Tuple ) => any ) extends ( ( _: infer First, ..._1: infer Rest ) => any ) ? IsFinite : never, infinite: Infinite, }[ Tuple extends [] ? 'empty' : Tuple extends Array ? Element[] extends Tuple ? 'infinite' : 'nonEmpty' : never ] type _Concat = { 'emptyLeft': Right, 'singleLeft': Left extends [infer SoleElement] ? Prepend : never, 'multiLeft': ( ( ..._: Reverse ) => any ) extends ( ( _: infer LeftLast, ..._1: infer ReversedLeftRest ) => any ) ? _Concat< Reverse< ReversedLeftRest >, Prepend< Right, LeftLast > > : never, 'infiniteLeft': { ERROR: 'Left is not finite', CODENAME: 'InfiniteLeft' & 'Infinite', }, }[ Left extends [] ? 'emptyLeft' : Left extends [any] ? 'singleLeft' : IsFinite ] export type Tail = ( ( ...t: Tuple ) => void ) extends ( ( h: any, ...rest: infer R ) => void ) ? R : never export type Init = Reverse>> type IsNestedArray = A extends any[][] ? T : F export type FlattenOnce = DeepFlatten export type Append = Reverse, B>> export type Concat< A extends any[], B > = B extends any[] ? _Concat : Append < A, B > export type Head = ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? First : ValueAt type RemoveItem = { 'skip': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? Concat : never, 'add': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? RemoveItem> : never, }[ A extends [] ? N : ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? First extends R ? 'skip' : 'add' : never ] /** Essentials */ export type Primitive = string | number | boolean | undefined | null /** Dictionaries related */ export type Dictionary = { [key in K]: T } export type DictionaryValues = T extends Dictionary ? U : never /** Like Partial but recursive */ export type DeepPartial = { [P in keyof T]?: T[P] extends Array ? Array> : T[P] extends ReadonlyArray ? ReadonlyArray> : DeepPartial } export type StrictPartial = { [K in keyof P]: K extends keyof O ? O[K] : never } export type DeepPartialFlexibleType = { [P in keyof T]?: T[P] extends Array ? Array> : T[P] extends ReadonlyArray ? ReadonlyArray> : DeepPartialFlexibleType } /** Like Readonly but recursive */ export type DeepReadonly = T extends Primitive ? T : T extends Array ? ReadonlyArray : T extends AnyFunction ? T : DeepReadonlyObject type DeepReadonlyObject = { readonly [P in keyof T]: DeepReadonly } // /** Omit given key in object type */ // export type Omit = Pick> /** Easy create opaque types ie. types that are subset of their original types (ex: positive numbers, uppercased string) */ export type Opaque = T & { __TYPE__: K } // type RemoveProp = { [P in keyof T]: string} // type Z = RemoveProp<{a: 1, b: 2}> // type vv = asf // type sf = Prepend<[1, 2], 3> // export type FlattenOnce = A extends Array // ? U // : never export type FlattenType = { 'deeper': A extends Array ? U extends any[] ? FlattenType : never : never, 'done': A extends Array< infer U> ? U : never, }[ A extends Array > ? 'deeper' : 'done' ] export type Identity = ( a: A ) => A export type WidenType = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends symbol ? symbol // tslint:disable-next-line:ban-types : T extends Function ? Function : T extends object ? object : T extends undefined ? undefined : T extends null ? null : T type _Deeper = 'deeper' | 'next' // next type _Pass = 'flattenType' | 'markInfinite' | 'error' | 'pass' type _Advance = 'advance' | 'advanceWide' // interface DeepFlattenInterface { // 'advance': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // ? DeepFlatten< Next, Concat< [ N ], [ First ]>, Deeper, Advance, Pass> // : never // 'advanceWide': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // ? DeepFlatten< Next, N extends any[] ? Concat< [ N ], [ WidenType ]> : never, Deeper, Advance, Pass> // : never // 'deeper': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // ? DeepFlatten< Next, IsFinite extends true // ? IsFinite extends true // ? Concat, First> // : never // : never, Deeper, Advance, Pass> // : never, // 'pass': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // ? DeepFlatten< Next, N extends any[] ? Append< N, First> : never, Deeper, Advance, Pass> // : never // 'flattenType': 1, // 'markInfinite': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // ? DeepFlatten< Next, N extends any[] ? Concat< [ N ], [ 'infinite' ] > : never, Deeper, Advance, Pass> // : never // 'error': { // ERROR: 'Infinite Item', // TEXT: 'Encountered an infinite item, evaluation haulted', // } // 'done': N, // } export type DeepFlatten = { // @ts-ignore 'advance': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // @ts-ignore ? DeepFlatten< Next, N extends any[] ? _Concat< N, First> : never, Deeper, Advance, Pass> : never 'advanceWide': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // @ts-ignore ? DeepFlatten< Next, N extends any[] ? _Concat< N, WidenType> : never, Deeper, Advance, Pass> : never 'deeper': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // @ts-ignore ? DeepFlatten< Next, N extends any[] ? _Concat< N, DeepFlatten> : never, Deeper, Advance, Pass> : never // @ts-ignore 'pass': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? DeepFlatten< Next, N extends any[] ? Append< N, First> : never, Deeper, Advance, Pass> : never // @ts-ignore 'flattenType': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // @ts-ignore ? DeepFlatten< Next, N extends any[] ? Append< N, FlattenType> : never, Deeper, Advance, Pass> : never 'markInfinite': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // @ts-ignore ? DeepFlatten< Next, N extends any[] ? _Concat< N, 'infinite'> : never, Deeper, Advance, Pass> : never 'error': { ERROR: 'Infinite Item', TEXT: 'Encountered an infinite item, evaluation haulted', } 'done': N, }[ A extends [] ? 'done' : ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? First extends any[] ? IsFinite < First > extends true ? Deeper : Pass // or error/markInfinite? : 'advance' : never ] export type BasicTypes = string|number|boolean|symbol|object|undefined|null|void|never export type WidenArray < T extends any[ ] > = T extends Array ? U[] : T /** * Deeply flattens a tuple and widens literals to general types */ export type DeepFlattenAndGeneralizeTuple < T extends any[] > = WidenArray < DeepFlatten < T, [], 'deeper', 'advanceWide', 'flattenType' >> export type ContainsInfinite = { 'next': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? ContainsInfinite< Next, Prepend> : never 'done': false, 'found': true, }[ A extends [] ? 'done' : ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // @ts-ignore ? IsFinite extends true ? 'next' : 'found' : 'done' ] export type ContainsType = { 'next': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? ContainsType< Next, Prepend> : never 'done': false, 'found': true, }[ A extends [] ? 'done' : ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? T extends First ? 'found' : 'next' : 'done' ] type _DeepFlattenNoInfinite = ContainsInfinite extends true ? DeepFlattenAndGeneralizeTuple : T /** * Deeply flatten a type, keeps literals unless there is an infinite type found */ export type DeepFlattenNoInfinite = { 'generalize': _DeepFlattenNoInfinite, }[ T extends any[] ? 'generalize' : never ] export type Equals = A extends B ? B extends A ? T : F : F export type Contains = { 'next': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? Contains : never 'found': T 'done': F, }[ A extends [] ? 'done' : ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? Equals : never ] export type Unique = { 'exclude': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? Unique : never 'include': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? R extends ( [] | [any, ...any[]] ) // @ts-ignore ? Unique, O> : Unique : never 'never': 'never' 'simplify': WidenArray 'done': R, }[ A extends [] ? 'done' : ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) // @ts-ignore ? IsFinite extends true ? Contains : 'simplify' : never ] // @ts-ignore export type AppendUnique = { 'next': Append 'done': A, }[ Contains ] export type Indices = Exclude // export type Literal ] = [ ( A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P ), ...Array ] > = Narrow export type Literal ] = [ ( A | B | C ), ...Array ] > = Narrow export type KeySubset = Exclude< keyof E, Extract > extends never ? true : false // extends keyof E ? keyof E : never export type HashKey = 'uuS*4_G]Sv<4eu-P""1giCjl3K~nLl[m>ePO9m/1ys?7:LH&A)MCr:a8g{X};8b' export type IsAny = HashKey extends O ? any extends O ? T : F : F export type ContainsAny = { 'next': ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? ContainsAny > : never 'found': T 'done': F, }[ A extends [] ? 'done' : ( ( ..._: A ) => any ) extends ( ( _: infer First, ..._1: infer Next ) => any ) ? IsAny : 'done' ] export type AnyObject = {[K in string ]: any} export type IsArray = A extends Array ? T : F export type Merge = { 'merge': { [I in keyof C]: I extends keyof B ? B[I] : C[I] } 'done': {[I in string]: unknown}, 'array': 'ERROR: this type function is not design to merge arrays', }[ IsArray > > ] // type Unshift = ( ( h: Element, ...t: Tuple ) => void ) extends ( ...t: infer R ) => void ? R : never // export type Append = // ( ( h: H, ...t: T ) => any ) extends ( ( ...l: infer L ) => any ) ? L : never // export type Reverse = { // 0: R, // 1: ( ( ...l: L ) => any ) extends ( ( h: infer H, ...t: infer T ) => any ) ? // Reverse> : // never, // }[L extends [any, ...any[]] ? 1 : 0] // export type Push, T extends any[]= ToTuple> = Reverse> // type Reverse = Reverse_; // type Reverse_ = { // 1: Result, // 0: Reverse_, Unshift>> // }[Tuple extends [] ? 1 : 0]; // type Concat, T extends any[]= ToTuple> = Concat_ // type Concat_ = { // 1: Reverse, // 0: Concat_>, Tail>, // }[Tuple2 extends [] ? 1 : 0] // type x = Concat<[1, 2, 3], [4, 5, 6]> // [1, 2, 3, 4, 5, 6] export type AnyFunction = ( ...args: any[] ) => any export type ExtractFunctionArguments < Fn > = Fn extends ( ...args: infer P ) => any ? P : never export type ExtractFunctionReturnValue = Fn extends ( ...args: any[] ) => infer P ? P : never export type ItemInsideIterable = { 'iterable': I extends Iterable ? U : never 'nodelist': I extends NodeListOf ? U : never, }[ I extends Iterable ? 'iterable' : I extends NodeListOf ? 'nodelist' : never ]