在查看 tslint 规则的源代码时,我遇到了以下语句:
if (node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
注意
!
之后的 node.parent
运算符。有趣!
我首先尝试使用当前安装的 TS 版本(1.5.3)在本地编译该文件。由此产生的错误指向了爆炸的确切位置:
$ tsc --noImplicitAny memberAccessRule.ts
noPublicModifierRule.ts(57,24): error TS1005: ')' expected.
接下来,我升级到最新的TS(2.1.6),编译没有问题。所以这似乎是 TS 2.x 的一个特性。 但是,转译完全忽略了爆炸,导致以下 JS:
if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
我的 Google fu 到目前为止让我失望了。
TS的感叹号运算符是什么,它是如何工作的?
这就是非空断言运算符。这是一种告诉编译器“这个表达式不能是
null
或 undefined
的方式,所以不要抱怨它是 null
或 undefined
的可能性。”有时类型检查器本身无法做出该决定。
在 TypeScript 发行说明中对此进行了解释:
新的
后缀表达式运算符可用于在类型检查器无法得出结论的情况下断言其操作数非空且非未定义。具体来说,操作
!
会生成x!
类型的值,其中排除x
和
null
。与
undefined
和
<T>x
形式的类型断言类似,
x as T
非空断言运算符在发出的 JavaScript 代码中被简单地删除。
!
我发现在该解释中使用术语“断言”有点误导。它是“断言”,意思是“开发人员断言它”,而不是要执行测试。最后一行确实表明它不会发出任何 JavaScript 代码。
bang 运算符告诉编译器暂时放宽它可能要求的“非空”约束。它对编译器说:“作为开发人员,我比你更清楚这个变量现在不能为空”。
null
或
undefined
以外的值。当编译器无法确定地推断类型但我们比编译器拥有更多信息时,这可能很有用。示例
TS码
function simpleExample(nullableArg: number | undefined | null) {
const normal: number = nullableArg;
// Compile err:
// Type 'number | null | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.(2322)
const operatorApplied: number = nullableArg!;
// compiles fine because we tell compiler that null | undefined are excluded
}
请注意,JS 不知道非空断言运算符的概念,因为这是 TS 功能
"use strict";
function simpleExample(nullableArg) {
const normal = nullableArg;
const operatorApplied = nullableArg;
}
let obj: { field: SampleType } | null | undefined;
... // some code
// the type of sampleVar is SampleType
let sampleVar = obj!.field; // we tell compiler we are sure obj is not null & not undefined so the type of sampleVar is SampleType
!
运算符执行与
NonNullable
相同的操作。let ns: string | null = ''
// ^? let ns: string | null
let s1 = ns!
// ^? let s1: string
let s2 = ns as NonNullable<typeof ns>
// ^? let s2: string
TypeScript 执行严格的 null 检查以帮助捕获潜在的 null 或未定义错误。当您尝试访问可能为 null 或未定义的变量上的成员(属性或方法)时,TypeScript 会引发编译错误。
let myElement: HTMLElement | null = document.getElementById('myElement');
// Without non-null assertion operator
// Compiler error: Object is possibly 'null'.
myElement.innerHTML = 'Hello, world!';
// With non-null assertion operator
myElement!.innerHTML = 'Hello, world!';
let referenceA: string | null = null
const n = 1
if (n) {
referenceA= "Hello My World!"
}
console.log(referenceA.toLowerCase()) // Error: Object is possibly 'null'.ts(2531)
为了避免该错误,我们需要使用“!”告诉编译器该变量不能为 Null运算符,称为非空断言运算符。
let referenceA: string | null = null
const n = 1
if (n) {
referenceA= "Hello My World!"
}
console.log(referenceA!.toLowerCase())