发布
社区首页 >问答首页 >“函数表达式,没有返回类型注释,在添加void操作时隐式地具有‘任意’返回类型”。

“函数表达式,没有返回类型注释,在添加void操作时隐式地具有‘任意’返回类型”。
EN

Stack Overflow用户
提问于 2022-01-10 08:59:20
回答 2查看 11.5K关注 0票数 3

我在TypeScript上有一个奇怪的问题。我最近了解了void ...操作符,因为我需要应用它,这样eslint就不会报告no-floating-promises。然而,这个特别的片段不知怎么地引起了一个问题,我不能在TypeScript游乐场上重现。

代码语言:javascript
代码运行次数:0
复制
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

代码语言:javascript
代码运行次数:0
复制
{
    "compileOnSave": true,
    "compilerOptions": {
        "noImplicitAny": true,
        "noEmitOnError": true,
        "sourceMap": true,
        "target": "ESNext",
        "module": "ESNext"
    },
    "exclude": [
        "node_modules"
    ]
}

我理解它可以通过添加: void返回类型或删除void操作或删除noImplicitAny来修复。

代码语言:javascript
代码运行次数:0
复制
window.setTimeout((): void => void this.onTickAsync(true), 200);

我想问:是什么导致了错误?为什么它只发生在我的IDE/本地而不是操场上?

当然,这不仅仅是因为VS代码,我还在一个单独的终端上运行了tsc --versiontsc

tsc --showConfig输出:

代码语言:javascript
代码运行次数:0
复制
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之间有一些不同):

代码语言:javascript
代码运行次数:0
复制
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));
  }

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-10 20:34:49

有关权威的答案,请参见微软/打字稿#36651

您的问题是您已经启用了编译器选项,但是还没有启用编译器选项。您可以在TypeScript游乐场并复制你的问题中设置这些选项。

旁白:请注意,--strictNullChecks编译器特性系列的一部分,通常建议将其作为事实上的类型安全“标准”级别的一部分。您并不是真正地询问应该使用哪些编译器选项,但是请注意,如果您使用了一组不常见的编译器选项,那么您更有可能遇到一般TypeScript社区并不熟悉的编译器行为。好了,够了。

所以我们知道如何复制,但还没有明确地回答为什么这里有一个错误。现在就这么做吧。启用--strictNullChecks后,光学器生成类型值。但是如果禁用了--strictNullChecks,就没有真正的undefined类型,而void运算符会生成一个类型值。除非显式地将一个类型称为注解,否则您将在--noImplicitAny下得到一个错误

代码语言:javascript
代码运行次数:0
复制
// 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操作符的返回类型被赋予了语境类型,您也可以消除错误。

代码语言:javascript
代码运行次数:0
复制
function foo(cb: () => any) { }
foo(() => void 0); // okay, void 0 is contextually typed as any

请注意,Function接口有点奇怪,没有真正的呼叫签名,请参阅微软/打字稿#20007,因此不能提供上下文类型:

代码语言:javascript
代码运行次数:0
复制
function bar(cb: Function) { }
bar(() => void 0); // implicit any error!

操场链接到代码

票数 2
EN

Stack Overflow用户

发布于 2022-01-10 09:19:33

我可以重现您的问题,尽管我无法回答为什么会发生这种情况,但是您可以通过省略运算符并将catch方法链接到满足ESLint的承诺来修复编译器错误:

代码语言:javascript
代码运行次数:0
复制
// before
window.setTimeout(() => void this.onTickAsync(true), 200);

// after
window.setTimeout(() => this.onTickAsync(true).catch(() => {}), 200);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70649907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档