UNPKG

@apoyo/std

Version:
1,881 lines (1,874 loc) 112 kB
declare const isNumber: (value: unknown) => value is number; declare const isNaN: (value: number) => boolean; declare const isNull: <A>(value: A | null) => value is null; declare const isUndefined: <A>(value: A | undefined) => value is undefined; declare const isObject: (input: unknown) => input is Record<string | number | symbol, unknown>; declare const isFunction: (input: unknown) => input is Function; declare function filter$2<A, B extends A>(fn: Dict.Refinement<A, B>): (dict: Dict<A>) => Dict<B>; declare function filter$2<A>(fn: Dict.Predicate<A>): (arr: Dict<A>) => Dict<A>; declare function reject$2<A, B extends A>(fn: Dict.Refinement<A, B>): (arr: Dict<A>) => Dict<InverseRefinement<A, B>>; declare function reject$2<A>(fn: Dict.Predicate<A>): (arr: Dict<A>) => Dict<A>; declare function omit(props: string[]): <A>(obj: Dict<A>) => Dict<A>; declare function pick(props: string[]): <A>(obj: Dict<A>) => Dict<A>; declare type Dict<A = any> = Record<string, A>; declare namespace Dict { interface Predicate<A> { (value: A, key: string): boolean; } interface Refinement<A, B extends A> { (value: A, key: string): value is B; } } declare const Dict: { /** * @description * Check if object is empty * * @example * ```ts * expect(Dict.isEmpty({})).toBe(true) * ``` */ isEmpty: (dict: Dict<unknown>) => boolean; /** * @description * Get the value of a specific key from the dict * * @see `Dict.get` * * @example * ```ts * const value = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.lookup('lastName') * ) * * expect(value).toBe('Doe') * ``` */ lookup: (key: string | number) => <A>(dict: Dict<A>) => Option<A>; /** * @description * Get the value of a specific key from the dict * * @see `Dict.lookup` * * @example * ```ts * const value = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.get('lastName') * ) * * expect(value).toBe('Doe') * ``` */ get: (key: string | number) => <A>(dict: Dict<A>) => Option<A>; /** * @description * Set the value of a specific key in a `Dict` * * @sideEffects this method mutates the given `Dict` * * @example * ```ts * const original = { * firstName: 'John' * } * const mutated = pipe( * original, * Dict.set('lastName', 'Doe') * ) * * expect(mutated === original).toBe(true) * expect(mutated.lastName).toBe('Doe') * ``` */ set: <A_1>(key: string | number, value: A_1) => (dict: Dict<A_1>) => Dict<A_1>; /** * @description * Calls a defined callback function on each element of a `Dict`. * This function returns a new `Dict` that contains the results. * * @param fn - How to map each value * * @see `Dict.mapIndexed` if you need the key * * @example * ```ts * const result = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.map(Str.upper) * ) * * expect(attrs !== result).toBe(true) * expect(result.firstName).toBe('JOHN') * expect(result.lastName).toBe('DOE') * ``` */ map: <A_2, B>(fn: (value: A_2) => B) => (dict: Dict<A_2>) => Dict<B>; /** * @description * Calls a defined callback function on each element of a `Dict`. * This function returns a new `Dict` that contains the results. * * @param fn - How to map each value * * @see `Dict.map` if you don't need the key * * @example * ```ts * const result = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.map((str, key) => `${key} = ${str}`) * ) * * expect(attrs !== result).toBe(true) * expect(result.firstName).toBe('firstName = John') * expect(result.lastName).toBe('lastName = Doe') * ``` */ mapIndexed: <A_3, B_1>(fn: (value: A_3, key: string) => B_1) => (dict: Dict<A_3>) => Dict<B_1>; /** * @description * Filter items out of the array * * @param fn - Predicate or refinement on which items to keep in the `Dict` * * @see `Dict.reject` * @see `Dict.filterMap` * * @example * ```ts * const result = pipe( * { * nb1: 1, * nb2: -3, * nb3: 2, * }, * Dict.filter(value => value >= 0) * ) * * expect(result).toEqual({ * nb1: 1, * nb3: 2 * }) * ``` */ filter: typeof filter$2; /** * @description * Filter items out of the array * * @param fn - Predicate or refinement on which items to remove from the `Dict` * * @see `Dict.filter` * @see `Dict.filterMap` * * @example * ```ts * const result = pipe( * { * nb1: 1, * nb2: -3, * nb3: 2, * }, * Dict.reject(value => value >= 0) * ) * * expect(result).toEqual({ * nb2: -3 * }) * ``` */ reject: typeof reject$2; /** * @description * Map and filter `undefined` values out of the `Dict` * * @param fn - How to map each value of the `Dict` * * @see `Dict.filter` * @see `Dict.reject` * @see `Dict.compact` * * @example * ```ts * const result = pipe( * { * firstName: "John", * lastName: null * }, * Dict.filterMap(value => value !== null * ? pipe(value, Str.upper) * : undefined * ) * ) * * expect(result).toEqual({ * firstName: "JOHN" * }) * ``` */ filterMap: <A_4, B_2>(fn: (value: A_4, key: string) => Option<B_2>) => (dict: Dict<A_4>) => Dict<B_2>; /** * @description * Filter `undefined` values out of the `Dict` * * @see `Dict.filterMap` * * @example * ```ts * const values = pipe( * { * firstName: "John", * lastName: undefined * }, * Dict.compact * ) * * expect(values).toEqual({ * firstName: "John" * }) * ``` */ compact: <A_5>(value: Dict<Option<A_5>>) => Dict<A_5>; /** * @description * Iterate through and accumulate / aggregate a value with a `Dict` * * @example * ```ts * const value = pipe( * { * nb1: 2, * nb2: 5, * nb3: 3 * }, * Dict.reduce((a, b) => a + b, 0) * ) * * expect(value).toEqual(10) * ``` */ reduce: <A_6, B_3>(fn: (acc: B_3, value: A_6, key: string) => B_3, initial: B_3) => (dict: Dict<A_6>) => B_3; /** * @description * Map over a `Dict` and return an array * * @see `Dict.keys` * @see `Dict.values` * @see `Dict.toPairs` * * @example * ```ts * const arr = pipe( * { * nb1: 1, * nb2: -3, * nb3: 2 * }, * Dict.collect((value, key) => [key, value]) * ) * * expect(arr).toEqual([ * ['nb1', 1], * ['nb2', -3], * ['nb3', 2] * ]) * ``` */ collect: <A_7, B_4>(fn: (value: A_7, key: string) => B_4) => (dict: Dict<A_7>) => B_4[]; /** * @description * Checks if the variable is an object */ isDict: (input: unknown) => input is Dict<unknown>; /** * @description * Collect all keys of the `Dict` * * @see `Dict.collect` * @see `Dict.values` * @see `Dict.toPairs` * * @example * ```ts * const arr = Dict.keys({ firstName: 'John' }) * expect(arr).toEqual(['firstName']) * ``` */ keys: <A_8>(dict: Dict<A_8>) => Array<string>; /** * @description * Collect all values of the `Dict` * * @see `Dict.collect` * @see `Dict.keys` * @see `Dict.toPairs` * * @example * ```ts * const arr = Dict.values({ firstName: 'John' }) * expect(arr).toEqual(['John']) * ``` */ values: <A_9>(dict: Dict<A_9>) => A_9[]; /** * @description * Create a dict from an array of key/value pairs * * @see `Dict.toPairs` * * @example * ```ts * const dict = Dict.fromPairs([ * ['firstName', 'John'], * ['lastName', 'Doe'] * ]) * expect(dict).toEqual({ * firstName: 'John', * lastName: 'Doe' * }) * ``` */ fromPairs: <A_10>(pairs: [string | number, A_10][] | (readonly [string | number, A_10])[]) => Dict<A_10>; /** * @description * Create an array of key/value pairs from the `Dict` * * @see `Dict.collect` * @see `Dict.keys` * @see `Dict.values` * @see `Dict.fromPairs` * * @example * ```ts * const arr = Dict.toPairs({ * firstName: 'John', * lastName: 'Doe' * }) * expect(arr).toEqual([ * ['firstName', 'John'], * ['lastName', 'Doe'] * ]) * ``` */ toPairs: <A_11>(dict: Dict<A_11>) => [string, A_11][]; /** * @description * Merge both `Dict`s. * The values of the member `Dict` have higher priority than the original `Dict`. * * As such, this method corresponds to: * ```ts * { * ...original, * ...member * } * ``` * * @param member - The `Dict` with which the original `Dict` should be combined * * @example * ```ts * const merged = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.concat({ * lastName: 'Smith', * gender: 'M' * }) * ) * * expect(merged).toEqual({ * firstName: 'John', * lastName: 'Smith', * gender: 'M' * }) * ``` */ concat: <A_12>(member: Dict<A_12>) => (dict: Dict<A_12>) => Dict<A_12>; /** * @description * Merge both `Dict`s. * The values of the original `Dict` have higher priority than the member `Dict`. * * As such, this method corresponds to: * ```ts * { * ...member, * ...original * } * ``` * * @param member - The `Dict` with which the original `Dict` should be combined * * @example * ```ts * const merged = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.union({ * lastName: 'Smith', * gender: 'M' * }) * ) * * expect(merged).toEqual({ * firstName: 'John', * lastName: 'Doe', * gender: 'M' * }) * ``` */ union: <A_13>(member: Dict<A_13>) => (dict: Dict<A_13>) => Dict<A_13>; /** * @description * Intersection of both `Dict`s based on their keys. * This means, only the keys that are both in `member` and the original `Dict` will be kept. * * @param member - The `Dict` with which the original `Dict` should be intersected * * @example * ```ts * const intersection = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.intersect({ * lastName: 'Smith', * gender: 'M' * }) * ) * * expect(intersection).toEqual({ * lastName: 'Doe' * }) * ``` */ intersect: <A_14>(member: Dict<A_14>) => (dict: Dict<A_14>) => Dict<A_14>; /** * @description * The difference between both `Dict`s based on their keys. * This means, all keys in `member` will be removed from the original `Dict`. * * @param member - The `Dict` with all keys to remove from the original `Dict` * * @example * ```ts * const diff = pipe( * { * firstName: 'John', * lastName: 'Doe' * }, * Dict.difference({ * lastName: 'Smith', * gender: 'M' * }) * ) * * expect(diff).toEqual({ * firstName: 'John' * }) * ``` */ difference: <A_15>(member: Dict<A_15>) => (dict: Dict<A_15>) => Dict<A_15>; /** * @description * Returns a new dict without the specified keys */ omit: typeof omit; /** * @description * Returns a new dict containing only the specified keys */ pick: typeof pick; }; declare type Falsy = null | undefined | '' | 0 | false; declare type None = undefined; declare type Some<A> = A extends undefined ? never : A; declare function filter$1<A, B extends A>(fn: Refinement<A, B>): (value: Option<A>) => Option<B>; declare function filter$1<A>(fn: Predicate<A>): (value: Option<A>) => Option<A>; declare function reject$1<A, B extends A>(fn: Refinement<A, B>): (value: Option<A>) => Option<B>; declare function reject$1<A>(fn: Predicate<A>): (value: Option<A>) => Option<A>; declare function get(onNone: () => never): <A>(value: Option<A>) => never; declare function get(onNone: () => never[]): <A extends any[]>(value: Option<A>) => Some<A>; declare function get(defaultValue: never[]): <A extends any[]>(value: Option<A>) => Some<A>; declare function get<B>(onNone: () => B): <A>(value: Option<A>) => Some<A> | B; declare function get<B>(defaultValue: B): <A>(value: Option<A>) => Some<A> | B; declare function throwError$1<A>(onNone: () => Error): (value: Option<A>) => A; declare function throwError$1<A>(err: Error): (value: Option<A>) => A; declare type Option<A> = A | undefined; declare namespace Option { type OptionProps<A extends Dict<unknown>> = { [P in keyof A]: A[P] extends Some<A[P]> ? never : P; }[keyof A]; type SomeProps<A extends Dict<unknown>> = { [P in keyof A]: A[P] extends Some<A[P]> ? P : never; }[keyof A]; export type Struct<A> = A extends Dict<unknown> ? { [P in SomeProps<A>]: A[P] extends Dict<unknown> ? Struct<A[P]> : A[P]; } & { [P in OptionProps<A>]?: A[P] extends Dict<unknown> ? Struct<A[P]> : A[P]; } : A; export {}; } /** * @namespace Option * * @description * * The `Option` namespace contains utilities to improve the handling of optional values. * The `Option` type is expressed as following: * * ```ts * type Option<A> = A | undefined * ``` * * **Note**: In other libraries, the `Option` type is often either `Some` value, or `None` / `Nothing`. * */ declare const Option: { /** * @description * Check if an optional value is not `undefined` */ isSome: <A>(value: Option<A>) => value is A; /** * @description * Check if an optional value is `undefined` */ isNone: <A_1>(value: Option<A_1>) => value is undefined; /** * @description * Map over an optional value, without worrying about the value being undefined * * @example * ```ts * const a: Option<number> = undefined * const b = pipe( * a, * Option.map(nb => nb * 2) * ) * * expect(b).toBe(undefined) * ``` */ map: <A_2, B>(fn: (value: A_2) => Option<B>) => (value: Option<A_2>) => Option<B>; /** * @description * If the predicate is false, the value becomes `undefined` * * @see `Option.reject` * * @example * ```ts * const result = pipe( * NaN, * Option.filter(nb => !isNaN(nb)) * ) * * expect(result).toBe(undefined) * ``` */ filter: typeof filter$1; /** * @description * If the predicate is true, the value becomes `undefined` * * @see `Option.filter` * * @example * ```ts * const result = pipe( * NaN, * Option.reject(nb => isNaN(nb)) * ) * * expect(result).toBe(undefined) */ reject: typeof reject$1; /** * @description * For a given `Option<A>`, returns either: * - The value `A` * - The given default value if the optional value is `undefined` * * @see `Option.throwError` * * @example * ```ts * const a: Option<number> = undefined * const b: number = pipe( * nb, * Option.get(0) * ) * * expect(b).toBe(0) * ``` */ get: typeof get; /** * @description * For a given `Option<A>`, either: * - Return the value `A` * - Throw the given error if the optional value is `undefined` * * @see `Option.get` * * @example * ```ts * const a: Option<number> = undefined * const b: number = pipe( * nb, * Option.get(0) * ) * * expect(b).toBe(0) * ``` */ throwError: typeof throwError$1; /** * @description * Returns an optional value from a nullable value * * @example * ```ts * const a: number | null = null * const b: Option<number> = Option.fromNullable(a) * * expect(b).toBe(undefined) * ``` */ fromNullable: <T>(value: T | null) => Option<T>; /** * @description * Returns an optional value from a falsy value * * **Note**: In Javascript, a falsy value may be undefined, null, 0, false and "" * * @example * ```ts * const a: number = 0 * const b: Option<number> = Option.fromFalsy(a) * * expect(b).toBe(undefined) * ``` */ fromFalsy: <T_1>(value: Falsy | T_1) => Option<T_1>; /** * @description * Returns an optional value from an empty string * * @example * ```ts * const a: string = "" * const b: Option<string> = Option.fromString(a) * * expect(b).toBe(undefined) * ``` */ fromString: <T_2>(value: string | T_2) => Option<string | T_2>; /** * @description * Returns an optional value from a number * * @example * ```ts * const a: number = NaN * const b: Option<number> = Option.fromNumber(a) * * expect(b).toBe(undefined) * ``` */ fromNumber: (value: number) => Option<number>; /** * @description * Returns an optional value from a Date object * * @example * ```ts * const a: Date = new Date("invalid") * const b: Option<Date> = Option.fromDate(a) * * expect(b).toBe(undefined) * ``` */ fromDate: (value: Date) => Option<Date>; }; /** * @description * A constant enum for possible `Ord` results * * @example * ```ts * expect(Ord.number(1, 0)).toBe(Ordering.UP) * expect(Ord.number(0, 1)).toBe(Ordering.DOWN) * expect(Ord.number(0, 0)).toBe(Ordering.EQ) * ``` */ declare const enum Ordering { UP = 1, DOWN = -1, EQ = 0 } declare function concat<A>(...ords: [Ord<A>]): Ord<A>; declare function concat<A, B>(...ords: [Ord<A>, Ord<B>]): Ord<A & B>; declare function concat<A, B, C>(...ords: [Ord<A>, Ord<B>, Ord<C>]): Ord<A & B & C>; declare function concat<A, B, C, D>(...ords: [Ord<A>, Ord<B>, Ord<C>, Ord<D>]): Ord<A & B & C & D>; declare function concat<A, B, C, D, E>(...ords: [Ord<A>, Ord<B>, Ord<C>, Ord<D>, Ord<E>]): Ord<A & B & C & D & E>; declare function concat<A, B, C, D, E, F>(...ords: [Ord<A>, Ord<B>, Ord<C>, Ord<D>, Ord<E>, Ord<F>]): Ord<A & B & C & D & E & F>; declare function eq<A>(ord: Ord<A>): { <X extends A, Y extends A>(x: X, y: Y): boolean; <Y_1 extends A>(y: Y_1): <X_1 extends A>(x: X_1) => boolean; }; declare function lt<A>(ord: Ord<A>): { <X extends A, Y extends A>(x: X, y: Y): boolean; <Y_1 extends A>(y: Y_1): <X_1 extends A>(x: X_1) => boolean; }; declare function lte<A>(ord: Ord<A>): { <X extends A, Y extends A>(x: X, y: Y): boolean; <Y_1 extends A>(y: Y_1): <X_1 extends A>(x: X_1) => boolean; }; declare function gt<A>(ord: Ord<A>): { <X extends A, Y extends A>(x: X, y: Y): boolean; <Y_1 extends A>(y: Y_1): <X_1 extends A>(x: X_1) => boolean; }; declare function gte<A>(ord: Ord<A>): { <X extends A, Y extends A>(x: X, y: Y): boolean; <Y_1 extends A>(y: Y_1): <X_1 extends A>(x: X_1) => boolean; }; declare function min<A>(ord: Ord<A>): { <X extends A, Y extends A>(x: X, y: Y): X | Y; <Y_1 extends A>(y: Y_1): <X_1 extends A>(x: X_1) => Y_1 | X_1; }; declare function max<A>(ord: Ord<A>): { <X extends A, Y extends A>(x: X, y: Y): X | Y; <Y_1 extends A>(y: Y_1): <X_1 extends A>(x: X_1) => Y_1 | X_1; }; declare type Ord<A> = { name: string; (a: A, b: A): Ordering; }; /** * @namespace Ord * * @description * This namespace contains utilities to create simple or more complex ordering / sorting functions. * * These `Ord` functions can be used for a multitude of use-cases: * * @see `Arr.sort` - To sort an array * @see `Arr.min` - To return the smallest value in an array * @see `Arr.max` - To return the biggest value in an array * */ declare const Ord: { /** * @description * Order strings */ string: Ord<string>; /** * @description * Order numbers */ number: Ord<number>; /** * @description * Order booleans. * * The value `false` comes first. */ boolean: Ord<boolean>; /** * @description * Order date object. * * This function does not check if the date is valid */ date: Ord<Date>; /** * @description * Create an order function for a custom type or object * * @example * ```ts * const ordTodo = pipe( * Ord.string, * Ord.contramap((todo: Todo) => todo.title) * ) * ``` */ contramap: <A, B>(fn: (value: A) => B) => (ord: Ord<B>) => Ord<A>; /** * @description * Inverse the order function * * @example * ```ts * const numberDesc = pipe( * Ord.number, * Ord.inverse * ) * * const nbs = pipe( * [1,3,2,4], * Arr.sort(numberDesc) * ) * * expect(nbs).toEqual([4,3,2,1]) * ``` */ inverse: <A_1>(ord: Ord<A_1>) => Ord<A_1>; /** * @description * Allow the ordering function to take optional (undefined) values. * * Undefined values are placed last. * * @see `Ord.nullable` for nullable values * * @example * ```ts * const optionalNb = pipe( * Ord.number, * Ord.optional * ) * * const nbs = pipe( * [1,3,undefined,2], * Arr.sort(optionalNb) * ) * * expect(nbs).toEqual([1,2,3,undefined]) * ``` */ optional: <A_2>(ord: Ord<A_2>) => Ord<Option<A_2>>; /** * @description * Allow the ordering function to take nullable values. * * Nullable values are placed last. * * @see `Ord.optional` for optional (undefined) values * * @example * ```ts * const optionalNb = pipe( * Ord.number, * Ord.nullable * ) * * const nbs = pipe( * [1,3,null,2], * Arr.sort(optionalNb) * ) * * expect(nbs).toEqual([1,2,3,null]) * ``` */ nullable: <A_3>(ord: Ord<A_3>) => Ord<A_3 | null>; /** * @description * Combine multiple `Ord`s. * * The first `Ord` is executed first. * If the elements are equal, the second `Ord` is executed, and so forth... * * @example * ```ts * const ordDone = pipe( * Ord.boolean, * Ord.contramap((todo: Todo) => todo.done) * ) * const ordName = pipe( * Ord.string, * Ord.contramap((todo: Todo) => todo.name) * ) * * // Order first by "done", then by "name" * const ordTodo = Ord.concat(ordDone, ordName) * * const todos = pipe( * todos, * Arr.sort(ordTodo) * ) * ``` */ concat: typeof concat; /** * @description * Create "equals" comparator from `Ord` * * @example * ```ts * const eqName = pipe( * Ord.string, * Ord.contramap((todo: Todo) => todo.name), * Ord.eq * ) * * // Find todo with the name "Buy bread" * const todo = todos.find(eqName("Buy bread")) * ``` */ eq: typeof eq; /** * @description * Create "lower than" comparator from `Ord` * * @see `Ord.lte` for "lower than equals" * @see `Ord.gt` for "greater than" * @see `Ord.gte` for "greater than equals" * * @example * ```ts * const ltNumber = pipe( * Ord.number, * Ord.lt * ) * * // Only retain numbers under 4 * const nbs = [1,3,6,2,4].filter(ltNumber(4)) * * expect(nbs).toEqual([1,3,2]) * ``` */ lt: typeof lt; /** * @description * Create "lower than equals" comparator from `Ord` * * @see `Ord.lt` for "lower than" * @see `Ord.gt` for "greater than" * @see `Ord.gte` for "greater than equals" * * @example * ```ts * const lteNumber = pipe( * Ord.number, * Ord.lte * ) * * // Only retain numbers under or equals to 4 * const nbs = [1,3,6,2,4].filter(lteNumber(4)) * * expect(nbs).toEqual([1,3,2,4]) * ``` */ lte: typeof lte; /** * @description * Create "greater than" comparator from `Ord` * * @see `Ord.lt` for "lower than" * @see `Ord.lte` for "lower than equals" * @see `Ord.gte` for "greater than equals" * * @example * ```ts * const gtNumber = pipe( * Ord.number, * Ord.gt * ) * * // Only retain numbers greater than 4 * const nbs = [1,3,6,2,4].filter(gtNumber(4)) * * expect(nbs).toEqual([6]) * ``` */ gt: typeof gt; /** * @description * Create "greater than equals" comparator from `Ord` * * @see `Ord.lt` for "lower than" * @see `Ord.lte` for "lower than equals" * @see `Ord.gt` for "greater than" * * @example * ```ts * const gteNumber = pipe( * Ord.number, * Ord.gte * ) * * // Only retain numbers greater or equals to 4 * const nbs = [1,3,6,2,4].filter(gteNumber(4)) * * expect(nbs).toEqual([6,4]) * ``` */ gte: typeof gte; /** * @description * Create a function which returns the smallest element from an `Ord` * * @see `Ord.max` * * @example * ```ts * const minDate = pipe( * Ord.date, * Ord.min * ) * * const date = minDate(new Date('2020'), new Date('2021')) * * expect(date).toBe(new Date('2020')) * ``` */ min: typeof min; /** * @description * Create a function which returns the greatest element from an `Ord` * * @see `Ord.min` * * @example * ```ts * const maxDate = pipe( * Ord.date, * Ord.max * ) * * const date = maxDate(new Date('2020'), new Date('2021')) * * expect(date).toBe(new Date('2021')) * ``` */ max: typeof max; }; declare function fromArray<A>(arr: Readonly<NonEmptyArray<A>>): NonEmptyArray<A>; declare function fromArray<A>(arr: NonEmptyArray<A>): NonEmptyArray<A>; declare function fromArray<A>(arr: A[]): Option<NonEmptyArray<A>>; declare type NonEmptyArray<A> = [A, ...A[]]; /** * @namespace NonEmptyArray * * @description * * A `NonEmptyArray` is an array containing at least 1 item. * This means, that some function will always return a value, compared to the `Arr` utility variant. * * **Note**: An `NonEmptyArray` variable can still use all of the utilities of the `Arr` namespace. * * ```ts * const arrayA: Array<number> = [] * const arrayB: NonEmptyArray<number> = [1] * * const a: Option<number> = Arr.head(arrayA) * const b: number = NonEmptyArray.head(arrayB) * ``` */ declare const NonEmptyArray: { /** * @description * Create a new NonEmptyArray, containing at least one element */ of: <A>(value: A) => NonEmptyArray<A>; /** * @description * Transforms an array into a `NonEmptyArray` * If the array is empty, the function will return `undefined` instead */ fromArray: typeof fromArray; /** * @description * Returns the first value in the `NonEmptyArray` * * @see `Arr.head` * @see `NonEmptyArray.last` * * @example * ```ts * const first = pipe( * [1,2,3,4], * Arr.head * ) * * expect(first).toEqual(1) * ``` */ head: <A_1>(arr: NonEmptyArray<A_1> | readonly [A_1, ...A_1[]]) => A_1; /** * @description * Returns the last value in the `NonEmptyArray` * * @see `Arr.last` * @see `NonEmptyArray.head` * * @example * ```ts * const last = pipe( * [1,2,3,4], * Arr.last * ) * * expect(last).toEqual(4) * ``` */ last: <A_2>(arr: NonEmptyArray<A_2> | readonly [A_2, ...A_2[]]) => A_2; /** * @description * Calls a defined callback function on each element of an `NonEmptyArray`, and returns a new `NonEmptyArray` that contains the results. * * @param fn - How to map each value * * @see `NonEmptyArray.mapIndexed` if you need the index * * @example * ```ts * const nbs = pipe( * [1,2,3], * NonEmptyArray.map(a => a + 1) * ) * * expect(nbs).toEqual([2,3,4]) * ``` */ map: <A_3, B>(fn: (value: A_3) => B) => (arr: NonEmptyArray<A_3> | readonly [A_3, ...A_3[]]) => NonEmptyArray<B>; /** * @description * Calls a defined callback function on each element of an `NonEmptyArray`, and returns a new `NonEmptyArray` that contains the results. * * @param fn - How to map each value * * @see `NonEmptyArray.map` if you don't need the index * * @example * ```ts * const nbs = pipe( * [1,2], * NonEmptyArray.mapIndexed((a, index) => `index ${index} = ${a}`) * ) * * expect(nbs).toEqual([ * `index 0 = 1`, * `index 1 = 2` * ]) * ``` */ mapIndexed: <A_4, B_1>(fn: (value: A_4, index: number) => B_1) => (arr: NonEmptyArray<A_4> | readonly [A_4, ...A_4[]]) => NonEmptyArray<B_1>; /** * @description * Returns the smallest value in the array. * * @param ord - The order is used to determine which element is smaller * * @see `Arr.min` * @see `NonEmptyArray.min` * * @example * ```ts * const smallestNb = pipe( * [1, 7, 3, 4, 2], * NonEmptyArray.min(Ord.number) * ) * * expect(smallestNb).toBe(1) * ``` */ min: <A_5>(ord: Ord<A_5>) => <C extends A_5>(arr: NonEmptyArray<C> | readonly [C, ...C[]]) => C; /** * @description * Returns the greatest value in the array. * * @param ord - The order is used to determine which element is greater * * @see `Arr.max` * @see `NonEmptyArray.min` * * @example * ```ts * const greatestNb = pipe( * [1, 7, 3, 4, 2], * NonEmptyArray.max(Ord.number) * ) * * expect(greatestNb).toBe(7) * ``` */ max: <A_6>(ord: Ord<A_6>) => <C_1 extends A_6>(arr: NonEmptyArray<C_1> | readonly [C_1, ...C_1[]]) => C_1; /** * @description * Sort array by the given `Ord` function. * * This function is the same as `Arr.sort`, but for `NonEmptyArray`s. * * @param ord - The order is used to determine which element is greater * * @example * ```ts * const nbs = pipe( * [1,4,2,3], * NonEmptyArray.sort(Ord.number) * ) * * expect(nbs).toEqual([1,2,3,4]) * ``` */ sort: <A_7>(ord: Ord<A_7>) => <C_2 extends A_7>(arr: NonEmptyArray<C_2> | readonly [C_2, ...C_2[]]) => NonEmptyArray<C_2>; }; declare const enum Tags { Ok = "Result.Ok", Ko = "Result.Ko" } interface Ok<T> { _tag: Tags.Ok; ok: T; } interface Ko<T> { _tag: Tags.Ko; ko: T; } declare type Struct<T extends Dict> = { [P in keyof T]: T[P] extends Ok<infer A> ? A : never; }; declare type StructErrors<T extends Dict> = { [P in keyof T]: T[P] extends Ko<infer E> ? E : never; }[keyof T]; declare type Result<A, E = unknown> = Ok<A> | Ko<E>; /** * @namespace Result * * @description * A `Result` can either `Ok` or `Ko`: * - `Ok` signifies the operation succeeded * - `Ko` signifies the operation failed * * A `Result`, being a simple variable, may also allow you to handle multiple operations that may fail, without throwing / stopping on the first failure * * @example * ```ts * const divide = (a, b) => { * if (b === 0) { * throw Err.of('cannot divide {a} by {b}', { a, b }) * } * return a / b * } * * const [ok, ko] = pipe( * [ [3,1], [3,0], [1,2], [4,0] ], * Arr.map(([a, b]) => Result.tryCatch(() => divide(a, b))), * Arr.separate * ) * ``` */ declare const Result: { /** * @description * Create an `Ok` value */ ok: <T>(value: T) => Ok<T>; /** * @description * Create a `Ko` value */ ko: <T_1>(value: T_1) => Ko<T_1>; /** * @description * Check if the result is `Ok` * * @example * ```ts * const result = Result.ok(1) * * if (Result.isOk(result)) { * console.log(result.ok) * } * ``` */ isOk: <A, B>(result: Result<A, B>) => result is Ok<A>; /** * @description * Check if the result is `Ko` * * @example * ```ts * const result = Result.ko(new Error('some error occured')) * * if (Result.isKo(result)) { * console.log(result.ko) * } * ``` */ isKo: <A_1, B_1>(result: Result<A_1, B_1>) => result is Ko<B_1>; /** * @description * Check if unknown variable is a `Result` */ isResult: <A_2 = unknown, B_2 = unknown>(result: unknown) => result is Result<A_2, B_2>; /** * @description * Create a `Result` from an optional value * * @example * ```ts * const user: Result<User, Error> = pipe( * users, * Arr.find(u => u.id === 'xxxx'), * Result.fromOption(() => new Error('could not find user')) * ) * ``` */ fromOption: <E = unknown>(onNone: () => E) => <A_3>(option: Option<A_3>) => Result<A_3, E>; /** * @description * Returns value if the result is `Ok`, or throws value if result is `Ko`. * * @description * ```ts * const result = Result.ko(new Error('some error')) * * try { * const value = Result.get(result) * } catch (err) { * expect(err.message).toBe('some error') * } * ``` */ get: <A_4, E_1 = unknown>(result: Result<A_4, E_1>) => A_4; /** * @description * Transforms the result into a tuple [ value, error ] * * @example * ```ts * const [value, error] = Result.tryCatch(() => { * throw new Error('Unknown') * }) * * expect(value).toBe(undefined) * expect(error?.message).toBe('Unknown') * ``` */ tuple: <A_5, E_2 = unknown>(result: Result<A_5, E_2>) => [Option<A_5>, Option<E_2>]; /** * @description * Map over the `Ok` value of the `Result`. * The callback is not called if the result is `Ko`. * * @see `Result.mapError` - If you want to map over the `Ko` value instead * * @example * ```ts * const result = pipe( * Result.ok(1), * Result.map(nb => nb + 1) * ) * * expect(result).toEqual(Result.ok(2)) * ``` */ map: <A_6, B_3>(fn: (value: A_6) => B_3) => <E_3 = unknown>(result: Result<A_6, E_3>) => Result<B_3, E_3>; /** * @description * Map over the `Ko` value of the `Result`. * The callback is not called if the result is `Ok`. * * @see `Result.map` - If you want to map over the `Ok` value instead * * @example * ```ts * const result = pipe( * Result.ko(new Error('some error')), * Result.mapError(Err.chain('operation failed')) * ) * ``` */ mapError: <B_4, E_4 = unknown>(fn: (value: E_4) => B_4) => <A_7>(result: Result<A_7, E_4>) => Result<A_7, B_4>; /** * @description * Flatten a `Result` in a `Ok` value * * @see `Result.chain` - Chain another operation returning a `Result` over an `Ok` value * @see `Result.catchError` - Chain another operation returning a `Result` over an `Ko` value * * @example * ```ts * const result: Result<Result<number, Error>, unknown> = pipe( * Result.ok(1), * Result.map(nb => nb >= 0 * ? Result.ok(nb + 1) * : Result.ko(new Error('only positives')) * ) * ) * * const after: Result<number, Error | unknown> = Result.join(result) * ``` */ join: <A_8, E_5>(result: Result<Result<A_8, E_5>, E_5>) => Result<A_8, E_5>; /** * @description * Chain another operation returning a `Result` over an `Ok` value * * @see `Result.catchError` - Chain another operation returning a `Result` over an `Ko` value * * @example * ```ts * const result: Result<number, Error | unknown> = pipe( * Result.ok(1), * Result.chain(nb => nb >= 0 * ? Result.ok(nb + 1) * : Result.ko(new Error('only positives')) * ) * ) * ``` */ chain: <A_9, B_5, E_6 = unknown>(fn: (value: A_9) => Result<B_5, E_6>) => (result: Result<A_9, E_6>) => Result<B_5, E_6>; /** * @description * Chain another operation returning a `Result` over an `Ko` value. * * @see `Result.chain` - Chain another operation returning a `Result` over an `Ok` value * * @example * ```ts * const result: Result<number, Error> = pipe( * Result.ko(Err.of('some error', { name: 'SomeError' })), * Result.catchError(err => pipe(err, Err.hasName('SomeError')) * ? Result.ok(1) * : Result.ko(err) * ) * ) * ``` */ catchError: <A_10, E_7 = unknown>(fn: (err: E_7) => Result<A_10, E_7>) => (result: Result<A_10, E_7>) => Result<A_10, E_7>; /** * @description * Fold over a `Result`: * - call `onOk` callback when the value is `Ok` * - call `onKo` callback when the value is `Ko` * * @see `Result.get` * * @example * ```ts * const str = pipe( * Result.ok(1), * Result.fold( * (value) => `Ok = ${value}`, * (err: Error) => `An error occured: ${err.message}` * ) * ) * * expect(str).toBe(`Ok = 1`) * ``` */ fold: <R, A_11, E_8 = unknown>(onOk: (value: A_11) => R, onKo: (value: E_8) => R) => (result: Result<A_11, E_8>) => R; /** * @description * Swap `Ok` and `Ko` value * * @example * ```ts * const result = pipe( * Result.ok(1), * Result.swap * ) * * expect(result).toEqual(Result.ko(1)) * ``` */ swap: <A_12, E_9>(result: Result<A_12, E_9>) => Result<E_9, A_12>; /** * @description * Try/catch an operation. The return value becomes the `Ok`, and the thrown value becomes the `Ko` * * @see `Result.fn` * * @example * ```ts * const divide = (a, b) => b === 0 * ? throwError(Err.of('cannot divide by zero')) * : a / b * * const result = Result.tryCatch(() => divide(1, 0)) * ``` */ tryCatch: <A_13>(fn: () => A_13) => Result<A_13, unknown>; /** * @description * Resultify the given function, making it return a `Result` instead of throwing / returning a normal value * * @see `Result.tryCatch` * * @example * ```ts * const divide = (a, b) => b === 0 * ? throwError(Err.of('cannot divide by zero')) * : a / b * * const [ok, ko] = pipe( * [ [1,2], [3,0], [2,3], [4,0] ], * Arr.map(Result.tryCatchFn(([a, b]) => divide(a, b))), * Arr.separate * ) * ``` */ tryCatchFn: <Args extends any[], T_2>(fun: (...args: Args) => T_2) => (...args: Args) => Result<T_2, unknown>; /** * @description * Takes a list of value as an input. * Applies the function one by one, and returns the first succeeding `Result` or all errors * * @example * ```ts * const numbers = [-2, -3, 1, -7, -12, -6] * * const firstPositive = Result.unionBy(nb => nb >= 0 * ? Result.ok(nb) * : Result.ko(`${nb} is negative`) * ) * * expect(pipe([-2, -3, 1, -7, -12], firstPositive)).toBe(1) * expect(pipe([-2, -3, -7, -12], firstPositive)).toEqual([ * `-2 is negative`, * `-3 is negative`, * `-7 is negative`, * `-12 is negative` * ]) * ``` */ unionBy: <T_3, A_14, E_10>(fn: (member: T_3, index: number) => Result<A_14, E_10>) => (members: NonEmptyArray<T_3>) => Result<A_14, E_10[]>; /** * @description * Returns the first succeeding `Result` or all errors * * @example * ```ts * const results = [Result.ko(`-2 is negative`), Result.ko(`-3 is negative`), Result.ok(1)] * * expect(pipe(results, Result.union, Result.get)).toBe(1) * ``` */ union: <A_15, E_11>(members: NonEmptyArray<Result<A_15, E_11>>) => Result<A_15, E_11[]>; /** * @description * Takes an object of values as an input and applies a function to all properties, to transform each property to a `Result`. * If all properties are `Ok`, return an `Ok` with all values. * If one or more properties are `Ko`, return the list of errors. * * @example * ```ts * const parseNbs = Result.structBy((prop, key) => { * const nb = parseInt(prop) * return isNaN(nb) * ? Result.ko(Err.of(`Invalid number {value} at property {key}`, { value, key })) * : Result.ok(nb) * }) * * const result1 = pipe( * { * a: "13", * b: "24", * d: "6" * }, * parseNbs * ) * * expect(pipe(result1, Result.get)).toEqual({ * a: 13, * b: 24, * d: 6 * }) * ``` */ structBy: <T_4, A_16, E_12>(fn: (prop: T_4, key: string) => Result<A_16, E_12>) => (props: Dict<T_4>) => Result<Dict<A_16>, E_12[]>; /** * @description * Takes an object of results as an input. * If all properties are `Ok`, return an `Ok` with all values. * If one or more properties are `Ko`, return the list of errors. * * @example * ```ts * const all = pipe( * { * a: Result.ok(13), * b: Result.ok(24), * d: Result.ok(6) * }, * Result.struct * ) * * expect(pipe(all, Result.get)).toEqual({ * a: 13, * b: 24, * d: 6 * }) * ``` */ struct: <T_5 extends Dict<Result<any, unknown>>>(props: T_5) => Result<Struct<T_5>, StructErrors<T_5>[]>; }; declare function filter<A, B extends A>(fn: Arr.Refinement<A, B>): (arr: A[]) => B[]; declare function filter<A>(fn: Arr.Predicate<A>): (arr: A[]) => A[]; declare function reject<A, B extends A>(fn: Arr.Refinement<A, B>): (arr: A[]) => InverseRefinement<A, B>[]; declare function reject<A>(fn: Arr.Predicate<A>): (arr: A[]) => A[]; declare function uniq<T>(arr: T[] | readonly T[]): T[]; declare function partition<A, B extends A>(fn: Refinement<A, B>): (arr: A[]) => [B[], InverseRefinement<A, B>[]]; declare function partition<A>(fn: Predicate<A>): (arr: A[]) => [A[], A[]]; declare type Arr<A = any> = Array<A>; declare namespace Arr { interface Predicate<A> { (value: A, index: number): boolean; } interface Refinement<A, B extends A> { (value: A, index: number): value is B; } } /** * @namespace Arr * * @description * * The `Arr` namespace contains all utilities related to Arrays. * * The utilities in this namespace are similar to the array utilities you can find in `underscore` or `lodash`. * * The big difference however is that they are pipeable, which means they can be chained like in the example below. * * ```ts * const nb = pipe( * [1,2,-3,4,-5], * Arr.map(a => a * 2), * Arr.filter(a => a >= 0), * Arr.last * ) * * expect(nb).toBe(8) * ``` * * @see `NonEmptyArray` namespace, if you are handling arrays containing at least one element. * */ declare const Arr: { /** * @description * Create array from value */ of: <A>(value: A) => NonEmptyArray<A>; /** * @description * Create array from an iterable */ from: <A_1>(value: Iterable<A_1> | A_1[]) => A_1[]; /** * @description * Get length of array */ length: <A_2>(arr: A_2[]) => number; /** * @description * Check if the variable is an array */ isArray: (arr: unknown) => arr is unknown[]; /** * @description * Check if the array is empty */ isEmpty: <A_3>(arr: A_3[]) => arr is []; /** * @description * Check if the array is non empty */ isNonEmpty: <A_4>(arr: A_4[]) => arr is NonEmptyArray<A_4>; /** * @description * Returns the first value in the array. * This function returns `undefined` when the array is empty. * * @example * ```ts * const first = pipe( * [1,2,3,4], * Arr.head * ) * * expect(first).toEqual(1) * ``` */ head: <A_5>(arr: A_5[]) => Option<A_5>; /** * @description * Returns the last value in the array. * This function returns `undefined` when the array is empty. * * @example * ```ts * const last = pipe( * [1,2,3,4], * Arr.last * ) * * expect(last).toEqual(4) * ``` */ last: <A_6>(arr: A_6[]) => Option<A_6>; /** * @description * Calls a defined callback function on each element of an array, and returns an array that contains the results. * * @param fn - How to map each value * * @see `Arr.mapIndexed` if you need the index * * @example * ```ts * const nbs = pipe( * [1,2,3], * Arr.map(a => a + 1) * ) * * expect(nbs).toEqual([2,3,4]) * ``` */ map: <A_7, B>(fn: (value: A_7) => B) => (arr: A_7[]) => B[]; /** * @description * Calls a defined callback function on each element of an array, and returns an array that contains the results. * * @param fn - How to map each value * * @see `Arr.map` if you don't need the index * * @example * ```ts * const nbs = pipe( * [1,2], * Arr.mapIndexed((a, index) => `index ${index} = ${a}`) * ) * * expect(nbs).toEqual([ * `index 0 = 1`, * `index 1 = 2` * ]) * ``` */ mapIndexed: <A_8, B_1>(fn: (value: A_8, index: number, arr: A_8[]) => B_1) => (arr: A_8[]) => B_1[]; /** * @description * Chain over array. * * @param fn - Map and return new array from value * * @see `Arr.chainIndexed` if you need the index * @see `Arr.map` * @see `Arr.flatten` * * @example * ```ts * const array = pipe( * [1,2,3], * Arr.chain(value => [value, value]) * ) * * expect(array).toEqual([1, 1, 2, 2, 3, 3]) * ``` */ chain: <A_9, B_2>(fn: (value: A_9) => B_2[]) => (arr: A_9[]) => B_2[]; /** * @description * Chain over an array with an index. * * @param fn - Map and return new array from value * * @see `Arr.chain` if you don't need the index * @see `Arr.map` * @see `Arr.flatten` * * @example * ```ts * const nbs = pipe( * [1,2], * Arr.chainIndexed((a, index) => [a, index]) * ) * * expect(nbs).toEqual([1,0,2,1]) * ``` */ chainIndexed: <A_10, B_3>(fn: (value: A_10, index: number, arr: A_10[]) => B_3[]) => (arr: A_10[]) => B_3[]; /** * @description * Check if at least one element in the array matches the predicate * * @see `Arr.every` * * @example * ```ts * const childrenAges = [8, 11, 19] * const hasAdult = pipe(childrenAges, Arr.some(age => age >= 18)) * * expect(hasAdult).toBe(true) * ``` */ some: <A_11>(fn: (value: A_11) => boolean) => (arr: A_11[]) => boolean; /** * @description * Check if all elements in the array match the predicate * * @see `Arr.some` * * @example * ```ts * const childrenAges = [8, 11, 19] * const allAdults = pipe(childrenAges, Arr.every(age => age >= 18)) * * expect(allAdults).toBe(false) * ``` */ every: <A_12>(fn: (value: A_12) => boolean) => (arr: A_12[]) => boolean; /** * @description * Join array values by the given separator */ join: (sep?: string) => <A_13>(arr: A_13[]) => string; /** * @description * Aggregate / accumulate all values in the array into a single value * * @example * ```ts * const nbs = [1,2,3,4] * const total = pipe( * nbs, * Arr.reduce((a, b) => a + b, 0) * ) * ``` */ reduce: <A_14, B_4>(fn: (acc: B_4, current: A_14) => B_4, initial: B_4) => (arr: A_14[]) => B_4; /** * @description * Filter items out of the array * * @param fn - Predicate or refinement on which items to remove from the array * * @see `Arr.filter` * @see `Arr.filterMap` * * @example * ```ts * const array = pipe( * [1,-2,3], * Arr.reject(value => value >= 0)