非空断言
先看以下代码:
function handler (arg: string | null | undefined) { let str: string = arg; // ... }
对于以上代码, TypeScript编译器会提醒以下错误信息:
Type 'string | null | undefined' is not assignable to type 'string'.Type 'undefined' is not assignable to type 'string'.
要解决以上问题,咱们能够加个条件判断:
function handler (arg: string | null | undefined) { let str: string; if (arg) { str = arg; } // ... }
此外, 能够应用TypeScript2.0中提供的非空断言操作符(non-null-assertion-operator
)。
语法
x!
非空断言操作符操作符 !
能够用于断言操作对象是非 null 和非 undefined 类型。即: x!
将从 x
值域中排除 null
和 undefined
。
所以以上代码能够革新为:
function handler (arg: string | null | undefined) { let str: string = arg!; // 没故障 str.split(''); // ... }
看下编译后果:
"use strict";function handler(arg) { let str = arg; str.split(''); // ... }
能够看出!
非空断言操作符从编译生成的JS代码中移除掉了, 如果handler函数调用时传入null
或undefined
时,会呈现以下运行时谬误:
Uncaught TypeError: Cannot read properties of undefined (reading 'split')
所以在理论应用时须要留神。留神:
非空断言操作符仅在启用 strictNullChecks
标记的时候才失效。当敞开该标记时,编译器不会查看 undefined 类型和 null 类型的赋值。
可选链运算符
先看以下代码:
type AlbumAPIResponse = { title: string; artist?: { name: string; bio?: string; previousAlbums?: string[]; };};const album: AlbumAPIResponse = { title: 'test'};const maybeArtistBio = album.artist && album.artist.bio || undefined;const maybeArtistBioElement = album ? album.artist ? album.artist.bio ? album.artist.bio : undefined: undefined :undefined; const maybeFirstPreviousAlbum = album.artist && album.artist.previousAlbums && album.artist.previousAlbums[0] || undefined;
为了获取bio
或者 previousAlbums
堪称是殚精竭虑。
当初能够应用TypeScript3.7中提供的可选链(Optional Chaining), 有了可选链后,咱们编写代码时如果遇到 null 或 undefined 就能够立刻进行某些表达式的运行,间接返回undefined .与函数调用一起应用时,如果给定的函数不存在,则返回 undefined。 外围是?.
操作符。
语法
obj?.prop
obj?.[expr]
arr?.[index]
func?.(args)
应用
可选属性拜访
那么以上代码就能够精简为:const maybeArtistBioElement = album?.["artist"]?.["bio"];const maybeFirstPreviousAlbum = album?.artist?.previousAlbums?.[0];
是不是精简很多了。
留神:
?.
与&&
并不是齐全等价。 &&
专门用于检测 falsy
值,比方空字符串、0、-0 、0n、NaN、null、undefined 和 false
等。而 ?.
只会验证对象是否为 null
或 undefined
,对于 0
或空字符串
来说,并不会呈现 “短路”
。
可选元素拜访
其行为相似于可选属性拜访,但容许咱们拜访非标识符属性(例如任意字符串、数字和symbol).
以下是基于索引拜访数组元素:function tryGetFirstElement<T>(arr?: T[]) { return arr?.[0];}
编译后果如下:
"use strict";function tryGetFirstElement(arr) { return arr === null || arr === void 0 ? void 0 : arr[0];}
所以在应用可链接后, 就不须要手动编写查看数组是否为null或undefined的保护性代码了。
尝试调用一个可能不存在的办法
async function makeRequest(url: string, log?: (msg: string) => void) { log?.(`Request started at ${new Date().toISOString()}`); // 以上代码等价于上面 // if (log != null) { // log(`Request started at ${new Date().toISOString()}`); // } const result = (await fetch(url)).json(); log?.(`Request finished at ${new Date().toISOString()}`); return result;}
空值合并运算符
先看以下代码:
interface AppConfiguration { name: string; items: number; active: boolean;}function updateApp(config: Partial<AppConfiguration>) { config.name = typeof config.name === "string" ? config.name : "(no name)"; config.items = typeof config.items === "number" ? config.items : -1; config.active = typeof config.active === "boolean" ? config.active : true;}
留神:
Partial<T>
将类型的属性变成可选
那么Partial<AppConfiguration>
相当于:
interface AppConfiguration { name?: string; items?: number; active?: boolean;}
以上代码中咱们须要先利用typeof判断属性类型是否正确,正确就赋值,否则就是默认值。
咱们不能应用||
, 因为
'' || "(no name)" ; // 值是"(no name)"不是 ""0 || -1; // 会返回-1false || true; // 会返回true
当初能够应用TypeScript3.7中提供的空值合并运算符。
当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数。。
与逻辑或 || 运算符不同,逻辑或会在左操作数为 falsy
值时返回右侧操作数。也就是说,如果你使⽤|| 来为某些变量设置默认的值时,你可能会遇到意料之外的⾏为。⽐如为 falsy 值(空字符串、0、-0 、0n、NaN、null、undefined 和 false
)时。
语法
leftExpr ?? rightExpr
应用
为常量提供默认值,保障常量不为 null 或者 undefined
以上代码可革新如下:function updateApp(config: Partial<AppConfiguration>) { config.name = config.name ?? "(no name)"; config.items = config.items ?? -1; config.active = config.active ?? true;}
短路
与 OR 和 AND 逻辑操作符类似,当左表达式不为 null 或 undefined 时,不会对右表达式进行求值。function A() { console.log('函数 A 被调用了'); return undefined; }function B() { console.log('函数 B 被调用了'); return false; }function C() { console.log('函数 C 被调用了'); return "foo"; }console.log( A() ?? C() );// 顺次打印 "函数 A 被调用了"、"函数 C 被调用了"、"foo"
编译后果(编译指标设为ES2015)如下:
"use strict";var _a;function A() { console.log('函数 A 被调用了'); return undefined; }function B() { console.log('函数 B 被调用了'); return false; }function C() { console.log('函数 C 被调用了'); return "foo"; }console.log((_a = A()) !== null && _a !== void 0 ? _a : C());
输入后果解释: A() 返回了 undefined,所以操作符两边的表达式都被执行了
留神:
不能与 AND 或 OR 操作符共用
将 ?? 间接与 AND(&&)和 OR(||)操作符组合应用是不可取的(该当是因为空值合并操作符和其余逻辑操作符之间的运算优先级/运算程序是未定义的)。
null || undefined ?? "foo"; // '||' and '??' operations cannot be mixed without parentheses.true || undefined ?? "foo"; // '||' and '??' operations cannot be mixed without parentheses.
然而,如果应用括号来显式表明运算优先级,是没有问题的:
(null || undefined ) ?? "foo";
参考资料
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator