When dealing with a function f: (X => Y) | undefined
that may be undefined, and x: X
is defined, we can utilize the optional chaining operator ?.
to apply f
to x
:
f?.(x) // This is fine even if `f` is undefined
However, if f: X => Y
is defined and x: X | undefined
could potentially be undefined, there doesn't seem to be a clear syntax for "mapping" f
over the "optional" x
:
f(?.x) // This syntax is not valid; It's ambiguous what to do when `x` is undefined
One approach could be implementing a function called pipeTo
, which changes the order of f
and x
, allowing it to work with ?.
as follows:
function opt<X>(x: X | undefined): { pipeTo<Y>(f: (a: X) => Y): Y } | undefined {
return typeof x === 'undefined' ? undefined : {
pipeTo<Y>(f: (a: X) => Y): Y {
return f(x)
}
}
}
This can then be used as opt(x)?.pipeTo(f)
. For instance:
function square(n: number): number { return n * n }
for (const x of [42, undefined, 58]) {
console.log(opt(x)?.pipeTo(square))
}
Is there a simpler standard solution available for applying a definite f
to a potentially undefined x
?
To clarify: "cumbersome" refers to anything that requires writing down the subexpression x
twice or adding meaningless helper variables to the code.