maybe
Conditionally applies a function only when the value is not null or undefined. If the value is nullish, maybe returns it unchanged. This makes maybe useful for optional normalization or validation steps where the absence of a value should short‑circuit the transformation.
maybe never mutates input and never throws. If the callback throws or returns a rejected Promise, maybe returns a rejected Promise instead of propagating the throw.
Signature
function maybe<T>(value: T): T;
function maybe<T, A>(
value: T | null | undefined,
fn: (value: T) => A | Promise<A>
): A | T | null | undefined | Promise<A | T | null | undefined>;
Parameters
Returns
One of:
- The original value — if it is
nullorundefined. - The transformed value — if the callback is synchronous.
- A
Promiseresolving to the transformed value — if the callback is asynchronous. - A
Promiserejecting with an error — if the callback throws or rejects.
Behavior
- Pure function: no side effects.
- Never mutates input.
- Never throws.
- Applies the callback only when the value is not nullish.
- If the callback returns a Promise, the pipeline becomes asynchronous.
- If the callback throws, the pipeline becomes asynchronous and returns a rejected Promise.
Examples
maybe(user.email, normalizeEmail)
maybe(input.age, validatePositiveInteger)
await maybe(user.id, async id => fetchUser(id))
maybe(null, x => x + 1)
Notes
- Intentionally minimal: it only checks for
nullandundefined. - Useful for optional fields, optional transformations, and conditional pipelines.
- Works seamlessly with pipe, compose, tap, and tryOrDefault.