Last updated
Last updated
논리 연산자를 대체할 수 있는 함수
type Predicate<T extends any[]> = (...args: T) => boolean;
type PredicateOperator = <T extends any[]>(
predicate: Predicate<T>
) => Predicate<T>;
type PredicateCombiner = <T extends any[]>(
...predicates: Predicate<T>[]
) => Predicate<T>;
/**
* @example
* const isOdd = not(isEven);
* isOdd(x) === !isEven(x); // true
*
*/
const not: PredicateOperator =
(predicate) =>
(...inputs) =>
!predicate(...inputs);
/**
* @example
* const isPositiveEven = all(isPositive, isEven);
* isPositiveEven(2); // true, both positive & even
* isPositiveEven(1); // false, only positive
* isPositiveEven(-2); // false, only even
*/
const all: PredicateCombiner =
(...predicates) =>
(...inputs) =>
predicates.every((predicate) => predicate(...inputs));
/**
* @example
* const isPositiveOrEven = any(isPositive, isEven)
* isPositiveOrEven(1); // true, positive
* isPositiveOrEven(-2); // true, even
* isPositiveOrEven(-3); // false, neither
*/
const any: PredicateCombiner =
(...predicates) =>
(...inputs) =>
predicates.some((predicate) => predicate(...inputs));
/**
* @example
* const isNotPostiveNorEven = none(isPositive, isEven);
* isNotPositiveNorEven(-3); // true, neither
* isNotPositiveNorEven(1); // false, positive
* isNotPositiveNorEven(-2); // false, even
*/
const none: PredicateCombiner = (...predicates) =>
not(any(...predicates));
/**
* @example
* const isEitherPositiveOrEven = xor(isPositive, isEven);
* isEitherPositiveOrEven(1); // true, only positive
* isEitherPositiveOrEven(2); // false, both positive & even
* isEitherPositiveOrEven(-3); // false, neither
*/
const xor: PredicateCombiner =
(...predicates) =>
(...inputs) => {
let hasTrue = false;
for (const predicate of predicates) {
if (!predicate(...inputs)) continue;
if (hasTrue) return false;
hasTrue = true;
}
return hasTrue;
};