在使用类型系统时,Declare 主要用于模拟值。在生产代码中,它很少使用。
declare name: string;
这对编译器说:
“有一个叫做name
type的属性string
。我不应该向你证明它name
确实存在,但我还是想使用它。”
该declare
关键字通常用于类型定义文件,这些文件为 Typescript 无法从中获取类型信息的文件(例如纯 JS 文件)提供类型。因此,如果我正在阅读您的代码,我会假设这name
是从某个 JS 文件中的某个地方修补了猴子,而您在这里注意到了这一点。
我会不正确。
name!: string;
这对编译器说:
“有一个名为name
类型的属性string | undefined
。它以 值开头undefined
。但是每次我获取或设置该属性时,我都想将其视为 type string
。”
使用这种形式,任何阅读最初未定义的代码的人都清楚name
,但无论如何都被视为字符串。这意味着它必须在这个文件的某个地方设置,只是可能不在构造函数中。
从你所说的来看,我在这些假设中是正确的。
在实践中,结果几乎相同。在这两种情况下,您都有一个不需要实际初始化的字符串属性。但是,我认为这对于name!: string
实际发生的事情要清楚得多。
此外,declare
从不发出代码。它使某些东西只存在于类型系统中。(感谢您提到这个@NoelDeMartin)
class Foo {
bar!: string;
declare baz: string;
}
let bar: string
declare let baz: string
编译为:
class Foo {
constructor() {
Object.defineProperty(this, "bar", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
}
}
let bar;
请注意,baz
输出中完全没有。
最后,我不得不提一下,你可能应该重构你的代码,以便你可以在构造函数中分配属性。这两种方法都不是类型安全的,因为您可能会将未初始化的值视为 a string
,如果发生这种情况可能会导致崩溃。