有时无法识别对象类型

时间:2020-12-22 15:46:25

标签: typescript visual-studio-code

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

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

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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

<块引用>

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

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

答案 1 :(得分: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 & Fooanyany["somePropKey"]any。最后一个,您 look up 一个属性并获得 any 是发生在 d.f2 的事情。只是any


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

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

Playground link to code