明确赋值断言和环境声明有什么区别?
当断言一个字段在类中肯定被初始化时,!(感叹号,明确赋值断言)和declare修饰符之间有什么区别?
以下代码在严格模式下是错误的,因为 TS 不确定该字段是否已初始化。
class Person {
name: string; // Error: Property 'name' has no initializer and is not definitely assigned in the constructor.
}
我见过两种处理方法:
- 明确赋值断言:
class Person { name!: string; } - 环境声明:
class Person { declare name: string; }
我看不出这两种技术之间的区别。它们都修复了错误,它们都不会发出代码,并且都不允许使用初始化程序。请问环境声明(在3.7版发布),只需过时明确赋值(在V2.7发布)?应该declare尽可能使用而不是使用!?
回答
declare name: string;
这对编译器说:
“有一个属性叫做
nametypestring。我不应该向你证明它name确实存在,但无论如何我想使用它。
该declare关键字通常用于类型定义文件,这些文件为 Typescript 无法从中获取类型信息的文件(例如纯 JS 文件)提供类型。因此,如果我正在阅读您的代码,我会假设name是从某处的某个 JS 文件中修补了猴子,而您在此处注意到了这一点。
我会是不正确的。
name!: string;
这对编译器说:
“有一个叫物业
name有型的string | undefined。它首先的价值undefined。但每次我获取或设置该属性,我希望把它当作类型string。”
使用这种形式,任何人都可以清楚地阅读一开始name未定义的代码,但无论如何都将其视为字符串。这意味着它必须在这个文件的某个地方设置,只是可能不在构造函数中。
从你所说的来看,我在这些假设中是正确的。
在实践中,结果是相同的。在这两种情况下,您都有一个字符串属性,您实际上不必对其进行初始化。但是,我认为name!: string实际上发生的事情要清楚得多。
最后,我不得不提一下,您可能应该重构您的代码,以便您可以在构造函数中分配属性。这两种方法都不是类型安全的,因为您可能会将未初始化的值视为 a string,如果发生这种情况可能会导致崩溃。