我在TypeScript上有一个奇怪的问题。我最近了解了void ...
操作符,因为我需要应用它,这样eslint
就不会报告no-floating-promises
。然而,这个特别的片段不知怎么地引起了一个问题,我不能在TypeScript游乐场上重现。
class A {
async a() {}
async onTickAsync(repeat: boolean) {
try {
await this.a();
} catch(e) {
console.error(e);
} finally {
if (repeat) {
window.setTimeout(() => void this.onTickAsync(true), 200);
}
}
}
}
VS代码将报告此错误:
TS7011:函数表达式,它没有返回类型注释,隐式地具有“任意”返回类型。
然而,这个问题在TS游乐场上是不可复制的。VS Code和游乐场都在使用TypeScript 4.5.4。这是我的tsconfig.json
{
"compileOnSave": true,
"compilerOptions": {
"noImplicitAny": true,
"noEmitOnError": true,
"sourceMap": true,
"target": "ESNext",
"module": "ESNext"
},
"exclude": [
"node_modules"
]
}
我理解它可以通过添加: void
返回类型或删除void
操作或删除noImplicitAny
来修复。
window.setTimeout((): void => void this.onTickAsync(true), 200);
我想问:是什么导致了错误?为什么它只发生在我的IDE/本地而不是操场上?
当然,这不仅仅是因为VS代码,我还在一个单独的终端上运行了tsc --version
和tsc
:
tsc --showConfig
输出:
PS C:\Users\lukev\Downloads\Temp> tsc --showConfig
{
"compilerOptions": {
"noImplicitAny": true,
"noEmitOnError": true,
"sourceMap": true,
"target": "esnext",
"module": "esnext"
},
"files": [
"./test.ts"
],
"exclude": [
"node_modules"
],
"compileOnSave": true
}
同样有趣的是,它不会发生在其他功能上。例如,这不会产生任何错误。这似乎与window.setTimeout
有关。例如,我发现Function
类型和() => void
之间有一些不同):
class A {
doSomething1(_: Function) { }
doSomething2(_: () => any) { }
doSomething3(_: () => void) { }
async a() { }
async onTickAsync(repeat: boolean) {
// Only this one produces error
this.doSomething1(() => void this.onTickAsync(true));
this.doSomething2(() => void this.onTickAsync(true));
this.doSomething3(() => void this.onTickAsync(true));
}
}
发布于 2022-01-10 20:34:49
有关权威的答案,请参见微软/打字稿#36651。
您的问题是您已经启用了编译器选项,但是还没有启用编译器选项。您可以在TypeScript游乐场并复制你的问题中设置这些选项。
旁白:请注意,--strictNullChecks
是编译器特性系列的一部分,通常建议将其作为事实上的类型安全“标准”级别的一部分。您并不是真正地询问应该使用哪些编译器选项,但是请注意,如果您使用了一组不常见的编译器选项,那么您更有可能遇到一般TypeScript社区并不熟悉的编译器行为。好了,够了。
所以我们知道如何复制,但还没有明确地回答为什么这里有一个错误。现在就这么做吧。启用--strictNullChecks
后,光学器生成类型值。但是如果禁用了--strictNullChecks
,就没有真正的undefined
类型,而void
运算符会生成一个类型值。除非显式地将一个类型称为注解,否则您将在--noImplicitAny
下得到一个错误
// with --strictNullChecks disabled
() => void 0; // error!
// Function expression, which lacks return-type annotation,
// implicitly has an 'any' return type.
(): undefined => void 0; // okay
//^^^^^^^^^^^ <-- arrow function return type annotation
正如您所看到的,如果void
操作符的返回类型被赋予了语境类型,您也可以消除错误。
function foo(cb: () => any) { }
foo(() => void 0); // okay, void 0 is contextually typed as any
请注意,Function
接口有点奇怪,没有真正的呼叫签名,请参阅微软/打字稿#20007,因此不能提供上下文类型:
function bar(cb: Function) { }
bar(() => void 0); // implicit any error!
发布于 2022-01-10 09:19:33
我可以重现您的问题,尽管我无法回答为什么会发生这种情况,但是您可以通过省略运算符并将catch
方法链接到满足ESLint的承诺来修复编译器错误:
// before
window.setTimeout(() => void this.onTickAsync(true), 200);
// after
window.setTimeout(() => this.onTickAsync(true).catch(() => {}), 200);
https://stackoverflow.com/questions/70649907
复制相似问题