【问题标题】:Object type is not recognized sometimes有时无法识别对象类型
【发布时间】:2021-04-01 07:59:36
【问题描述】:

我在 VS Code 中有以下 TypeScript 代码:

const f1 = ():string => { return "abc"; }

const d:any = {}
d.f2 = ():string => { return "abc"; }

将鼠标放在f1 上,它会显示const f1: () => string

将鼠标放在f2 上,它会显示any

f2不应该也是一个返回字符串的函数吗?

【问题讨论】:

  • noither 情况下,函数的返回类型是函数; f1 的返回类型是 string。但是,any 类型的 any 属性的类型也将是 any - 这就是 any 的含义
  • 标题应该被编辑,因为我们不涉及 return 类型。也许“编译器在赋值后忘记了类型?”或者其他的东西?这里的问题是“对使用非联合类型注释的变量的赋值不会缩小变量的类型”和“any 具有传染性”

标签: typescript visual-studio-code


【解决方案1】:

如果你有一个像这样的非联合类型Foo

interface Foo {
  a: string;
}

如果您将变量注释为该类型:

let foo: Foo = { a: "hello" };

那么任何后续赋值或属性更改将不会影响该变量的明显类型。例如:

let bar = { a: "hello", b: "goodbye" };
bar.b; // okay
foo = bar; // okay, bar is assignable to Foo
foo.b // <-- error! Property 'b' does not exist on type 'Foo'

这里我们有一个值bar,已知它有一个b 属性。我们可以将bar 分配给foo,因为bar 是一个有效的Foo(它有一个a 属性)。但是一旦我们完成了这个赋值,编译器并没有改变foo 的明显类型。它仍然只是Foo,因此我们无法再从中读取b 属性。

注意:对于联合类型,它更复杂,因为control flow analysis (microsoft/TypeScript#8010) 导致一些赋值显然将变量的类型缩小到联合成员的某个子集。但是根据a comment in microsoft/TypeScript#8513,他们还没有对非联合类型这样做。


您将d 注释为type any,这是一个非联合类型。之后,您分配的任何属性都将立即被遗忘。

此外,any 类型是类型系统的一个逃生舱口(参见this answer)。它具有传染性并向外传播到它所接触的许多其他类型:any | Fooanyany &amp; Fooanyany["somePropKey"]any。最后一个,你look up 一个属性并获得anyd.f2 发生的事情。只是any


如果你不希望这种情况发生,你应该远离any,而是使用更强大的类型,最好是更不可变的对象,并让编译器推断而不是在可能的情况下手动注释:

const d2 = {
  f2: () => { return "abc" }
}
d2.f2().toUpperCase(); // okay

Playground link to code

【讨论】:

    【解决方案2】:

    不,因为持有它的对象的类型为any,所以 Typescript 无法推断它总是一个函数。 any 的目的不是引发类型检查错误。如果它在这种情况下推断出函数类型,它还会阻止您分配具有不同类型的值,这可能是不希望的。

    当一个值是 any 类型时,您可以访问它的任何属性(这又是 any 类型)

    https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多