is-kit

predicate

Helpers to adapt boolean predicates to refinements.

import { predicateToRefine, and, isNumber } from 'is-kit';
const isPositive = predicateToRefine<number>((n) => n > 0);
const isPositiveNumber = and(isNumber, isPositive);
isPositiveNumber(3); // true
const isEvenBool = (n: number) => n % 2 === 0;
const isEvenRefine = predicateToRefine<number>(isEvenBool);
const isEvenNumber = and(isNumber, isEvenRefine);
isEvenNumber(3); // false
isEvenNumber(4); // true

True refinement (brand) example

When you want the type to actually narrow, define a true refinement on your side (e.g., a branded type) and compose it with and().

import { and, isNumber } from 'is-kit';
// True refinement (branded type) — the type actually narrows
type Positive = number & { readonly __brand: 'Positive' };
const isPositive = (n: number): n is Positive => n > 0;
const isPositiveNumber = and(isNumber, isPositive);
// (x: unknown) => x is Positive
function sqrtOfPositive(n: Positive): number { return Math.sqrt(n); }
const maybeNumber: unknown = 9;
if (isPositiveNumber(maybeNumber)) {
sqrtOfPositive(maybeNumber); // OK — narrowed to Positive
}