如何简洁地将已定义函数f应用于可能未定义的参数x?
将已定义函数应用于可选值的简洁方案
场景与痛点
- 当函数
f: (X => Y) | undefined可能未定义、但参数x: X已定义时,我们可以直接用可选链运算符?.实现安全调用:f?.(x) // 完全安全,f未定义时不会执行调用 - 但反过来,当函数
f: X => Y确定存在、但参数x: X | undefined可能未定义时,没有原生语法直接实现「仅当x存在时调用f」:f(?.x) // 无效语法,x未定义时的行为逻辑不明确
我自己实现了一个opt函数,通过交换f和x的顺序来适配可选链:
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) } } }
使用示例:
function square(n: number): number { return n * n } for (const x of [42, undefined, 58]) { console.log(opt(x)?.pipeTo(square)) }
核心问题:有没有更简洁的标准方案,可以把确定存在的f应用于可能未定义的x?
补充:这里的「繁琐」指需要重复书写
x,或用无意义辅助变量污染作用域。
可行的简洁标准方案
1. 短路求值(最原生简洁)
这是最直接的标准写法,无需额外工具函数:
x !== undefined && f(x)
如果需要同时处理null,可以写成:
x != null && f(x)
优点:原生语法、无依赖、可读性强;缺点:若f返回假值(如0、''),会返回该假值而非undefined,但多数场景下符合预期。
2. 条件判断+空值合并(统一返回undefined)
如果希望x未定义时统一返回undefined,可以用:
x != null ? f(x) : undefined // 或更紧凑的写法 x && f(x) ?? undefined
3. 极简工具函数(函数式风格)
如果频繁遇到这类场景,可以写一个比opt更精简的工具函数,语义更贴合函数式编程的「可选值映射」:
const maybe = <X>(x: X | undefined) => ({ map: <Y>(f: (a: X) => Y) => x != null ? f(x) : undefined })
使用方式:
maybe(x)?.map(f)
4. 链式场景适配
如果是在对象属性链式调用中,可以直接结合可选链:
// 示例:从对象中取可选属性后调用函数 const user = { profile: { age: undefined } } const formatAge = (n: number) => `年龄:${n}` const ageText = user.profile?.age != null ? formatAge(user.profile.age) : undefined
为什么没有f(?.x)这类语法?
ECMAScript标准委员会(TC39)曾讨论过类似的「可选参数」语法,但目前未纳入标准,核心原因是:
- 语义不明确:
x未定义时,f(?.x)应该返回undefined、不执行调用还是抛出错误? - 现有语法组合已经能覆盖需求,短路求值+可选链的方案足够简洁实用。
内容的提问来源于stack exchange,提问作者Andrey Tyukin
相关产品推荐
相关产品推荐

