unless()
unless<
T,Result>(value,predicate,transformation):T|Result
Applies a transformation to a value when a predicate is false, otherwise returns the original value.
This is the logical opposite of when.
π Why is this a Hidden Gem?
The logical inverse of when. Applies a transformation only if the predicate is false.
Logical opposite of when.
Type Parametersβ
T: Tβ
The type of the input value.
Result: Resultβ
The type of the transformed value.
Parametersβ
value: Tβ
The value to potentially transform.
predicate: (value) => booleanβ
A function that determines when NOT to apply the transformation.
transformation: (value) => Resultβ
The function to apply when the predicate is false.
Returns: T | Resultβ
The transformed value if predicate is false, otherwise the original value.
See Alsoβ
Sinceβ
2.0.0
Also known asβ
unless (Ramda) Β· β (Lodash, es-toolkit, Remeda, Radashi, Effect, Modern Dash, Antfu)
Exampleβ
unless(4, (n) => n % 2 !== 0, (n) => n * 2);
// => 8 (4 is not odd, so transformation applies)
unless(3, (n) => n % 2 !== 0, (n) => n * 2);
// => 3 (3 is odd, so no transformation)
unless('hello', (s) => s.trim() === '', (s) => s.toUpperCase());
// => 'HELLO' (not empty, so transformation applies)
unless('', (s) => s.trim() === '', (s) => s.toUpperCase());
// => '' (empty, so no transformation)
How it works?β
Applies a transformation only when the predicate returns false.
If predicate is true, returns the original value unchanged. Logical opposite of when.
Predicate False (transforms)β
Predicate True (skips)β
unless vs whenβ
| Input | when(x, isOdd, double) | unless(x, isOdd, double) |
|---|---|---|
| 3 (odd) | transforms β 6 | skips β 3 |
| 4 (even) | skips β 4 | transforms β 8 |
Use Casesβ
Add defaults only when missing πβ
Add 'https://' prefix only when URL doesn't already have it. Essential for URL normalization and ensuring valid links.
const ensureProto = (url) =>
unless(url, (u) => u.startsWith("http"), (u) => `https://${u}`);
ensureProto("google.com"); // "https://google.com"
ensureProto("https://site.com"); // "https://site.com"
Skip validation for admin usersβ
Apply validation rules only for non-admin users. Critical for permission systems and role-based logic.
const validate = (user) =>
unless(user, (u) => u.isAdmin, (u) => {
if (!u.email) throw new Error("Email required");
return u;
});
Lazy-load images unless already in viewportβ
Skip lazy-loading for images already visible on initial render. Essential for above-the-fold optimization and Core Web Vitals.
const maybeLazyLoad = (img: HTMLImageElement) =>
unless(img, (el) => el.getBoundingClientRect().top < window.innerHeight, (el) => {
el.loading = "lazy";
return el;
});
document.querySelectorAll("img").forEach(maybeLazyLoad);
Skip overlay backdrop on mobileβ
Skip rendering the backdrop overlay on mobile where it causes scroll issues. Perfect for responsive overlay components that behave differently on mobile.
const overlayConfig = (config: OverlayConfig) =>
unless(config, () => window.innerWidth >= 768, (c) => ({
...c,
hasBackdrop: false,
fullScreen: true,
}));
// Desktop: keeps backdrop, normal overlay
// Mobile: no backdrop, full screen sheet
Show tooltip unless touch deviceβ
Disable hover tooltips on touch devices where they cause UX issues. Perfect for design systems supporting both desktop and mobile.
const maybeTooltip = (content: string) =>
unless(content, () => "ontouchstart" in window, (text) => ({
tooltip: text,
showOnHover: true,
}));
maybeTooltip("Click to edit"); // Desktop: { tooltip: "Click to edit", showOnHover: true }
// Touch device: "Click to edit" (no tooltip wrapper)
transforms β 6
skips β 3