我在 VS Code 中有以下 TypeScript 代码:
const f1 = ():string => { return "abc"; }
const d:any = {}
d.f2 = ():string => { return "abc"; }
将鼠标放在 f1
上,它会显示 const f1: () => string
。
将鼠标放在 f2
上,它会显示 any
。
f2
不应该也是一个返回字符串的函数吗?
答案 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 | Foo
是 any
; any & Foo
是 any
; any["somePropKey"]
是 any
。最后一个,您 look up 一个属性并获得 any
是发生在 d.f2
的事情。只是any
。
如果您不希望这种情况发生,您应该远离 any
,而是使用更强的类型,最好是更不可变的对象,并让编译器推断而不是在可能的情况下手动注释:
const d2 = {
f2: () => { return "abc" }
}
d2.f2().toUpperCase(); // okay