UNPKG

remeda

Version:

A utility library for JavaScript and Typescript.

211 lines (210 loc) 19.5 kB
import { GuardType } from "./GuardType-ClHvIrsq.cjs"; //#region src/conditional.d.ts type Case<In, Out, When extends (x: In) => boolean = (x: In) => boolean> = readonly [when: When, then: (x: GuardType<When, In> & In) => Out]; type DefaultCase<In, Out> = (x: In) => Out; type Utilities = { readonly defaultCase: typeof defaultCase; }; type WithUtils<T> = T & Utilities; declare const conditionalPlus: WithUtils<typeof conditional>; /** * Executes a transformer function based on the first matching predicate, * functioning like a series of `if...else if...` statements. It sequentially * evaluates each case and, upon finding a truthy predicate, runs the * corresponding transformer, and returns, ignoring any further cases, even if * they would match. * * *NOTE*: Some type-predicates may fail to narrow the param type of their * transformer; in such cases wrap your type-predicate in an anonymous arrow * function: e.g., instead of * `conditional(..., [myTypePredicate, myTransformer], ...)`, use * `conditional(..., [($) => myTypePredicate($), myTransformer], ...)`. * * To add a a default, catch-all, case you can provide a single callback * function (instead of a 2-tuple) as the last case. This is equivalent to * adding a case with a trivial always-true predicate as it's condition (see * example). * * For simpler cases you should also consider using `when` instead. * * Due to TypeScript's inability to infer the result of negating a type- * predicate we can't refine the types used in subsequent cases based on * previous conditions. Using a `switch (true)` statement or ternary operators * is recommended for more precise type control when such type narrowing is * needed. * * !IMPORTANT! - Unlike similar implementations in Lodash and Ramda, the Remeda * implementation **doesn't** implicitly return `undefined` as a fallback when * when none of the cases match; and instead **throws** an exception in those * cases! You have to explicitly provide a default case, and can use * `constant(undefined)` as your last case to replicate that behavior. * * @param cases - A list of (up to 10) cases. Each case can be either: * - A 2-tuple consisting of a predicate (or type-predicate) and a transformer * function that processes the data if the predicate matches. * - A single callback function that acts as a default fallback case. * @returns The output of the matched transformer. If no cases match, an * exception is thrown. The return type is a union of the return types of all * provided transformers. * @signature * R.conditional(...cases)(data); * @example * const nameOrId = 3 as string | number | boolean; * * R.pipe( * nameOrId, * R.conditional( * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * ), * ); //=> 'Hello ID: 3' (typed as `string`), can throw!. * * R.pipe( * nameOrId, * R.conditional( * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * R.constant(undefined), * ), * ); //=> 'Hello ID: 3' (typed as `string | undefined`), won't throw. * * R.pipe( * nameOrId, * R.conditional( * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * (something) => `Hello something (${JSON.stringify(something)})`, * ), * ); //=> 'Hello ID: 3' (typed as `string`), won't throw. * @dataLast * @category Function */ declare function conditional<T, Fn0 extends (x: T) => boolean, Return0, Fallback = never>(case0: Case<T, Return0, Fn0>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Return0, Return1, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Return0, Return1, Return2, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Return3 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Return3 | Return4 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Fn7 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Return7, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, case7: Case<T, Return7, Fn7>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Return7 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Fn7 extends (x: T) => boolean, Fn8 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Return7, Return8, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, case7: Case<T, Return7, Fn7>, case8: Case<T, Return8, Fn8>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Return7 | Return8 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Fn7 extends (x: T) => boolean, Fn8 extends (x: T) => boolean, Fn9 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Return7, Return8, Return9, Fallback = never>(case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, case7: Case<T, Return7, Fn7>, case8: Case<T, Return8, Fn8>, case9: Case<T, Return9, Fn9>, fallback?: DefaultCase<T, Fallback>): (data: T) => Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Return7 | Return8 | Return9 | Fallback; /** * Executes a transformer function based on the first matching predicate, * functioning like a series of `if...else if...` statements. It sequentially * evaluates each case and, upon finding a truthy predicate, runs the * corresponding transformer, and returns, ignoring any further cases, even if * they would match. * * *NOTE*: Some type-predicates may fail to narrow the param type of their * transformer; in such cases wrap your type-predicate in an anonymous arrow * function: e.g., instead of * `conditional(..., [myTypePredicate, myTransformer], ...)`, use * `conditional(..., [($) => myTypePredicate($), myTransformer], ...)`. * * To add a a default, catch-all, case you can provide a single callback * function (instead of a 2-tuple) as the last case. This is equivalent to * adding a case with a trivial always-true predicate as it's condition (see * example). * * For simpler cases you should also consider using `when` instead. * * Due to TypeScript's inability to infer the result of negating a type- * predicate we can't refine the types used in subsequent cases based on * previous conditions. Using a `switch (true)` statement or ternary operators * is recommended for more precise type control when such type narrowing is * needed. * * !IMPORTANT! - Unlike similar implementations in Lodash and Ramda, the Remeda * implementation **doesn't** implicitly return `undefined` as a fallback when * when none of the cases match; and instead **throws** an exception in those * cases! You have to explicitly provide a default case, and can use * `constant(undefined)` as your last case to replicate that behavior. * * @param data - The input data to be evaluated against the provided cases. * @param cases - A list of (up to 10) cases. Each case can be either: * - A 2-tuple consisting of a predicate (or type-predicate) and a transformer * function that processes the data if the predicate matches. * - A single callback function that acts as a default fallback case. * @returns The output of the matched transformer. If no cases match, an * exception is thrown. The return type is a union of the return types of all * provided transformers. * @signature * R.conditional(data, ...cases); * @example * const nameOrId = 3 as string | number | boolean; * * R.conditional( * nameOrId, * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * ); //=> 'Hello ID: 3' (typed as `string`), can throw!. * * R.conditional( * nameOrId, * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * R.constant(undefined), * ); //=> 'Hello ID: 3' (typed as `string | undefined`), won't throw. * * R.conditional( * nameOrId, * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * (something) => `Hello something (${JSON.stringify(something)})`, * ); //=> 'Hello ID: 3' (typed as `string`), won't throw. * @dataFirst * @category Function */ declare function conditional<T, Fn0 extends (x: T) => boolean, Return0, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, fallback?: DefaultCase<T, Fallback>): Return0 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Return0, Return1, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Return0, Return1, Return2, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Return3 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Return3 | Return4 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Fn7 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Return7, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, case7: Case<T, Return7, Fn7>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Return7 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Fn7 extends (x: T) => boolean, Fn8 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Return7, Return8, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, case7: Case<T, Return7, Fn7>, case8: Case<T, Return8, Fn8>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Return7 | Return8 | Fallback; declare function conditional<T, Fn0 extends (x: T) => boolean, Fn1 extends (x: T) => boolean, Fn2 extends (x: T) => boolean, Fn3 extends (x: T) => boolean, Fn4 extends (x: T) => boolean, Fn5 extends (x: T) => boolean, Fn6 extends (x: T) => boolean, Fn7 extends (x: T) => boolean, Fn8 extends (x: T) => boolean, Fn9 extends (x: T) => boolean, Return0, Return1, Return2, Return3, Return4, Return5, Return6, Return7, Return8, Return9, Fallback = never>(data: T, case0: Case<T, Return0, Fn0>, case1: Case<T, Return1, Fn1>, case2: Case<T, Return2, Fn2>, case3: Case<T, Return3, Fn3>, case4: Case<T, Return4, Fn4>, case5: Case<T, Return5, Fn5>, case6: Case<T, Return6, Fn6>, case7: Case<T, Return7, Fn7>, case8: Case<T, Return8, Fn8>, case9: Case<T, Return9, Fn9>, fallback?: DefaultCase<T, Fallback>): Return0 | Return1 | Return2 | Return3 | Return4 | Return5 | Return6 | Return7 | Return8 | Return9 | Fallback; /** *! **DEPRECATED**: `conditional` now accepts a default, catch-all, callback directly and no longer needs this utility wrapper. Use `constant(undefined)` as your last case instead (see example). * * @example * const nameOrId = 3 as string | number; * R.conditional( * nameOrId, * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * // Was: `R.conditional.defaultCase(),`, Now: * constant(undefined), * ); //=> 'Hello ID: 3' * @deprecated `conditional` now accepts a default, catch-all, callback * directly and no longer needs this utility wrapper. Use `constant(undefined)` * as your last case instead (see example). */ declare function defaultCase(): Case<unknown, undefined>; /** *! **DEPRECATED**: `conditional` now accepts a default, catch-all, callback directly and no longer needs this utility wrapper. Simply put your `then` callback as the last case (see example). * * @param then - You only need to provide the transformer, the predicate is * implicit. @default () => undefined, which is how Lodash and Ramda handle * the final fallback case. * @example * const nameOrId = 3 as string | number; * R.conditional( * nameOrId, * [R.isString, (name) => `Hello ${name}`], * [R.isNumber, (id) => `Hello ID: ${id}`], * // Was: `R.conditional.defaultCase( * // (something) => `Hello something (${JSON.stringify(something)})`, * //),`, Now: * (something) => `Hello something (${JSON.stringify(something)})` * ); //=> 'Hello ID: 3' * @deprecated `conditional` now accepts a default, catch-all, callback * directly and no longer needs this utility wrapper. Simply put your `then` * callback as the last case. */ declare function defaultCase<In, Then extends (param: In) => unknown>(then: Then): Case<In, ReturnType<Then>>; //#endregion export { conditionalPlus }; //# sourceMappingURL=conditional-CQXW9kSy.d.cts.map