关于ESLint no-unsafe-optional-chaining规则未校验更安全可选链写法的疑问
关于ESLint no-unsafe-optional-chaining规则未校验更安全可选链写法的疑问
嘿,这个问题问到点子上了!我来给你捋清楚这里面的逻辑~
首先咱们先明确两种写法的差异:
- 当
obj是undefined时,obj?.foo()会直接返回undefined,不会报错——这是可选链的核心作用:短路跳过不存在的属性/对象。 - 但如果
obj是一个存在的空对象,obj?.foo会返回undefined,这时候再调用()就会抛出TypeError;而obj?.foo?.()会因为foo是undefined直接短路,不会执行调用,也就不会报错。
那为什么ESLint的no-unsafe-optional-chaining规则不强制大家都用更“安全”的obj?.foo?.()呢?主要有这几个原因:
1. ESLint是静态检查工具,没法预判运行时类型
ESLint只能分析代码的语法和静态结构,它没办法提前知道obj.foo到底是不是一个函数。比如你可能明确知道:只要obj存在,obj.foo就一定是可调用的函数,这时候obj?.foo()完全是合理的写法,ESLint没理由阻止你——总不能因为“万一foo不是函数”就强制所有人写冗余的代码吧?
2. 规则的设计目标是避免明确的不安全用法,而非强制过度保守
no-unsafe-optional-chaining规则的核心是帮你避开那些明显错误的可选链用法,比如:
obj?.foo()后面再加一个可选链(obj?.foo()?.bar),这时候如果obj.foo()返回undefined,调用bar会报错,规则会提示你这里有问题;- 或者在赋值语句左边用可选链(
obj?.foo = 1),这本身就是语法错误。
它不是要让你把所有调用都写成最保守的形式,而是帮你避免那些语法上就有问题,或者逻辑上肯定会出bug的用法。
3. 过度强制会导致代码冗余,违背JS的简洁性
如果ESLint强制所有可选链调用都写成obj?.foo?.(),那很多场景下会出现没必要的冗余代码。比如你已经通过类型约束或者业务逻辑确保obj.foo是函数,只是不确定obj是否存在,这时候obj?.foo()足够简洁且安全,强制改成obj?.foo?.()反而画蛇添足。
最后补充一点
如果你的业务场景中,obj存在但foo可能不是函数,那确实应该用obj?.foo?.()来避免报错。但这种场景下,ESLint没法帮你自动判断——如果你需要更严谨的类型检查,建议结合TypeScript使用:它可以通过类型定义提前告诉你obj.foo是否是可调用的,从根源上避免这类问题。
备注:内容来源于stack exchange,提问作者Littlee
相关产品推荐
相关产品推荐

