在返回never的函数中出现的TypeScript错误
我不明白这段脚本为什么会产生一个TypeScript错误:
"use strict";
const croak = (errMsg: string): never => {
console.error('CROAK' + ': ' + errMsg)
Deno.exit()
}
const main = (): never => {
croak("An error occurred")
}
main()
我得到如下错误:
Check src/temp/temp1.ts
TS2534 [ERROR]: A function returning 'never' cannot have a reachable end point.
const main = (): never => {
~~~~~
at file:///C:/Users/johnd/util/src/temp/temp1.ts:7:18
error: Type checking failed.
请注意,错误是在 main() 函数上,而不是 croak() 函数上。事实上,我可以把 croak() 函数放在一个单独的模块中,它编译时不会出现错误。
croak() 函数声明它永不返回。因此,当我调用 main() 函数时,我声明它永不返回;并且因为它调用的函数本身也永不返回,所以不应该出现TypeScript错误。至少我是这么理解的。
换句话说,除非我没看清楚,否则 main() 函数实际上并没有一个可到达的结束点。
我使用Deno作为运行时:
$ deno --version
deno 2.7.5 (stable, release, x86_64-pc-windows-msvc)
v8 14.6.202.9-rusty
typescript 5.9.2
解决方案
解决方法是确保你的 croak() 函数具有显式类型。
从最终用户的角度来看,这有点出乎意料,但事实证明这是预期行为。
这在实现“控制流分析中的断言”行为的那个 pull request 的末尾有说明。
具体来说,在原始注释的底部,它有如下表述(以下粗体为我标注):
当
- 调用发生在顶层表达式语句中,并且
- 调用为函数名指定了一个标识符或带点序列的标识符,且
- 函数名中的每个标识符引用一个具备显式类型的实体,且
- 函数名解析为具有an asserts返回类型的函数类型或具显式never返回类型注解的类型时,
那么一个函数调用会被分析为断言调用或永不返回的调用。
如果一个实体被视为具备显式类型,当它被声明为一个函数、方法、类或命名空间,或者作为具有显式类型注解的变量、参数或属性时。 (这一规则之所以存在,是为了让对潜在断言调用的控制流分析不会循环地触发进一步分析。)
下面是一些显式对函数进行类型化、以使其参与断言控制流的方法(注意,这并不是穷尽列表):
// ⚠️ this function will not trigger the assertion check because it has an implicit type
const croak = (errMsg: string): never => {
console.error('CROAK' + ': ' + errMsg)
Deno.exit()
}
// ✅ explicit type declaration (inline)
const croak2: (errMsg: string) => never = (errMsg: string): never => {
console.error('CROAK' + ': ' + errMsg)
Deno.exit()
}
// ✅ explcit type declaration (via type)
type NeverFn = (errMsg: string) => never;
const croak3: NeverFn = (errMsg: string): never => {
console.error('CROAK' + ': ' + errMsg)
Deno.exit()
}
// ✅ function declaration
function croak4(errMsg: string): never {
console.error('CROAK' + ': ' + errMsg)
Deno.exit()
}
这在此前的回答中也给出过这里,但没有对为何这是必需的或有哪些让显式类型化函数生效的替代方式进行详细解释。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。