fp-booleans
Version:
Utilities to apply boolean logic (not, and, or) to functions and higher-order functions. Tiny, tested and composable
52 lines (49 loc) • 3.21 kB
TypeScript
/**
* Type representing a function that given any number of parameters of any type returns a boolean
* e.g.: TPredicate<[number]> equals (n: number) => boolean
* e.g.: TPredicate<[number, string]> equals (n: number, str: string) => boolean
*/
export type TPredicate<T extends any[]> = (...params: T) => boolean;
/**
* Type representing a function that given any number of parameters of any type returns a TBoolean<any []>
* e.g.: THigherOrderBooleanPredicate<[number, string], [string]> equals (n: number, str: string) => (arg: string) => boolean
*/
export type THigherOrderPredicate<U extends any[], T extends any[]> = (...params: U) => TPredicate<T>;
/** Checking at runtime if a function is a predicate is difficult without parsing it.
The only way is to invoke it and check the type of the return value to be boolean.
To be able to invoke any function of any arity and arguments type, the only option invoke it without passing arguments.
Therefore, the predicate being tested must be resilient to be invoked without arguments.
Example:
BAD ❌ const hasLengthGreaterThanZero = (argument: string) => argument.length > 0;
Invoking it without arguments would throw "Cannot read properties of undefined (reading 'length')"
GOOD ✅ const hasLengthGreaterThanZero = (argument: string) => argument?.length > 0;
The return value being true or false, wrong or right, is not important. Must be a boolean and don't throw errors
when invoked without arguments.
*/
export declare const isPredicate: (arg: TPredicate<any[]> | THigherOrderPredicate<any[], any[]>) => arg is TPredicate<any[]>;
export declare const isHigherOrderPredicate: (arg: TPredicate<any[]> | THigherOrderPredicate<any[], any[]>) => arg is THigherOrderPredicate<any[], any[]>;
/**
* not() can
* 1. flip a boolean (e.g.: not(true) -> false)
* 2. invert the behaviour of a predicate (e.g.: not(isEven) -> isOdd)
* 3. invert the behaviour of a higher-order function that produces a predicate (e.g.: not(is)(5) -> isNot(5))
*/
export declare function not(value: boolean): boolean;
export declare function not<T extends any[]>(f: TPredicate<T>): TPredicate<T>;
export declare function not<U extends any[], T extends any[]>(f: THigherOrderPredicate<U, T>): THigherOrderPredicate<U, T>;
/**
* and() can:
* 1. asserts the truth of all elements in an array of booleans (e.g.: and(true, false) -> false)
* 2. construct a composite functions out of a list of predicates with the same signature (arity and types)
* where all predicates must succeed (e.g.: and(isPositive, isEven) -> isPositiveAndEven)
*/
export declare function and(...args: boolean[]): boolean;
export declare function and<T extends any[]>(...args: TPredicate<T>[]): TPredicate<T>;
/**
* or() can:
* 1. asserts the truth of at least one element in an array of booleans (e.g.: and(true, false) -> true)
* 2. construct a composite functions out of a list of predicates with the same signature (arity and types)
* where at least one predicate must succeed (e.g.: or(isPositive, isEven) -> isPositiveOrEven))
*/
export declare function or(...args: boolean[]): boolean;
export declare function or<T extends any[]>(...args: TPredicate<T>[]): TPredicate<T>;