为何TypeScript推断匿名函数never返回类型时缺少错误提示
TypeScript不同never返回类型声明的控制流分析差异解答
const willThrowException:(message:string)=>never = (message)=> { throw new Error(message); } try { willThrowException('some message'); willThrowException('another message'); // OK: 编译器会报错「检测到不可达代码」 } catch(e) {} const willThrowExceptionToo = (message:string):never=> { throw new Error(message); } try { willThrowExceptionToo('some message'); willThrowExceptionToo('another message'); // 不符合预期: 编译器不会报错 } catch(e) {}
差异原因
这个现象是TypeScript 4.3/4.4版本控制流分析的设计特性导致的,两种never返回类型的声明方式对应不同的校验规则:
- 第一种写法是给变量直接标注
(message:string) => never类型,相当于你主动向编译器承诺该函数调用后永远不会把控制权交还给调用方的下一行,无论是否包裹try/catch结构。编译器做控制流分析时会直接判定第一行调用后的代码不可达,因此触发不可达代码报错。 - 第二种写法是给箭头函数本身标注返回类型为never,此时TS的控制流分析会额外考虑异常捕获逻辑:函数抛出的错误可能被当前try块对应的catch块捕获,控制权会流转到catch块而非直接终止,因此不会判定try块内的第二行调用是不可达代码。
补充说明
虽然编辑器的类型补全能识别到第二种写法的函数返回类型为never,但目前版本的TS控制流分析没有对齐两种声明方式的处理规则,属于已知的实现差异。如果需要严格的不可达代码检测,优先使用变量层面的函数类型标注即可。
内容的提问来源于stack exchange,提问作者Zero Distraction
相关产品推荐
相关产品推荐

