问题描述
Class Employee {
firstName: string;
lastName!: string;
middleName?: string;
}
Employee
类的这3个不同字段中有什么区别?
解决方法
位于marks the property optional位置的?
。
该位置的!
是definite assignment assertion。它是non-null assertion operator的声明级版本,但用于属性(也可以用于变量)而不是表达式。
在此示例中有两个错误,或者可以说是三个错误:
-
Class
应该是class
; JavaScript和TypeScript区分大小写。 -
您需要在
firstName
上使用一个初始化程序(或无条件分配给它的构造函数)。 -
!
上的lastName
告诉TypeScript肯定会分配lastName
,从而抑制了您为firstName
遇到的那种错误,但是没有(在示例中)实际上做的分配是使用!
保证您知道自己正在执行TypeScript。
编辑:code you linked随后处理上述#1和#2,但不适用于#3。 TypeScript不会警告lastName
从未分配,并假定其值为字符串,而实际上它不存在,因此读取其值将导致undefined
。
它们很好地隐藏在documentation of TypeScript中。
?
在interfaces上进行了描述,它标记为optional property。
!
是definite assertion operator。它告诉编译器即使TypeScript的分析无法检测到该属性,也已设置了该属性(不是null
或undefined
)。
顺便说一句,Class
不是TypeScript或JavaScript关键字,并且会在该位置产生错误。他们用于声明类的关键字为class
。 TypeScript和JavaScript标识符和关键字区分大小写(Class
和class
是不同的东西)。
具有编译器选项strictNullChecks: false
如果您的strictNullChecks: false
中有tsconfig.json
,则它们是完全相同的,因为禁用strictNullChecks
意味着所有字段为空或未定义为有效值。
具有编译器选项strictNullChecks: true
class Employee {
firstName: string;
lastName!: string;
middleName?: string;
}
firstName: string
表示firstName
必须是string
。 null
或undefined
对于firstName无效。
所有字段的默认值为undefined
,这将导致错误Property 'firstName' has no initializer and is not definitely assigned in constructor
要使错误静音,您需要将声明更改为firstName: string = 'Some default value'
或添加一个构造函数并在构造函数中为其指定一个值。
constructor() {
this.firstName = 'some default value';
}
现在开始!句法。 lastName!: string
的语法与lastName: string
相似,因为它基本上说只有string
是唯一允许的类型。不允许使用null
和undefined
。但是它将使编译器无法确定分配错误。假设您有以下代码。
类员工{ firstName:字符串; lastName !:字符串; middleName ?:字符串;
constructor() {
// This will silence the compiler about first name not initialized
this.firstName = 'some default value';
// The compiler cannot tell that lastName is assigned in init() function
this.init();
}
private init(): void {
this.lastName = 'some default value';
}
}
在先前的代码中,lastName
肯定是通过constructor
调用在this.init()
中分配的。但是编译器不知道这一点。所以加了!基本上是告诉编译器“闭嘴,我知道我在做什么” 。然后由您来确保代码的正确性。
关于middleName?: string
语法。这与middleName: string | undefined
完全相同;由于所有值的默认值均为undefined
,因此编译器不会抱怨未分配middleName
。
这3个不同的Employee类字段有什么区别?
Employee实例执行以下操作:
- 需要具有名字,但它的值可以是字符串或null / undefined
- 需要具有lastName,并且其值不能为null / undefined。它必须是一个字符串。
- 可选地包含字符串的MiddleName或null / undefined