1. 首页

【TypeScript 进化史 — 1】non-nullable 的类型

在这篇文章中,我们将讨论发布于 TypeScript 2.0 中的 non-nullable 类型,这是对类型系统的一个重大的改进,该特性可对 nullundefined 的检查。cannot read property 'x' of undefinedundefined is not a function 在 JS 中是非常常见的错误,non-nullable 类型可以避免此类错误。

null 和 undefined 的值

TypeScript 2.0 之前,类型检查器认为 nullundefined 是每种类型的有效值。基本上,nullundefined 可以赋值给任何东西。这包括基本类型,如字符串、数字和布尔值:


let name: string; name = "Marius"; // OK name = null; // OK name = undefined; // OK let age: number; age = 24; // OK age = null; // OK age = undefined; // OK let isMarried: boolean; isMarried = true; // OK isMarried = false; // OK isMarried = null; // OK isMarried = undefined; // OK

number 类型为例。它的域不仅包括所有的IEEE 754浮点数,而且还包括两个特殊的值 nullundefined

对象、数组和函数类型也是如此。无法通过类型系统表示某个特定变量是不可空的。幸运的是,TypeScript 2.0 解决了这个问题。

严格的Null检查

TypeScript 2.0 增加了对 non-nullable 类型的支持,并新增严格 null 检查模式,可以通过在命令行上使用 ——strictNullChecks 标志来选择进入该模式。或者,可以在项目中的 tsconfig.json 文件启用 strictnullcheck 启用。


{ "compilerOptions": { "strictNullChecks": true // ... } }

在严格的 null 检查模式中,nullundefined 不再分配给每个类型。nullundefined 现在都有自己的类型,每个类型只有一个值

Js中文网 一个帮助开发者成长的社区,你想要的,在这里都能找到

如果咱们在编译前时启用了严格的 null 检查,如果将 nullundefined 分配给任何变量都会导致类型错误


// 使用 --strictNullChecks 编译 let name: string; name = "Marius"; // OK name = null; // Error name = undefined; // Error let age: number; age = 24; // OK age = null; // Error age = undefined; // Error let isMarried: boolean; isMarried = true; // OK isMarried = false; // OK isMarried = null; // Error isMarried = undefined; // Error

那么,如何在 TypeScript 2.0 中使变量为空?

用联合类型构建可空性

由于在启用严格的 null 检查时,类型在默认情况下是不可空的,所以我们需要显式指定可为空,并告诉类型检查器我们希望哪些变量为空。我们通过构造一个包含 nullundefined 类型的联合类型来实现这一点


let name: string | null; name = "Marius"; // OK name = null; // OK name = undefined; // Error

注意,undefined 不是 name 变量的有效值,因为联合类型不包含 undefined 类型

这种可空性方法的一大优点是,类型中哪些成员是可空的变得很明显,并且可以自文档化。以这个简单的 User 类型为例:


type User = { firstName: string; lastName: string | undefined; }; let jane: User = { firstName: "Jane", lastName: undefined }; let john: User = { firstName: "John", lastName: "Doe" };

我们可以通过添加 ?lastName 属性设为可选。这样就可以完全省略 las​​tName 属性的定义。 此外,undefined 的类型会自动添加到联合类型中。 因此,以下所有分配类型都是可以的:


type User = { firstName: string; lastName?: string; }; // 可以为 lastName 属性分配一个字符串 let john: User = { firstName: "John", lastName: "Doe" }; // 或者 undefined let jane: User = { firstName: "Jane", lastName: undefined }; // 还可以省略 let jake: User = { firstName: "Jake" };

可为空类型的属性访问

如果对象的类型包括 nullundefined,则访问任何属性都会产生编译时错误:


function getLength(s: string | null) { // Error: Object 可能为空 return s.length; }

在访问属性之前,需要使用类型保护来检查给定对象上的属性访问是否安全:


function getLength(s: string | null) { if (s === null) { return 0; } return s.length; }

TypeScript 是兼容 JS ,并支持条件表达式中的类型保护,所以这种方法也可以:


function getLength(s: string | null) { return s ? s.length : 0; }

使用可空类型的函数调用

如果试图调用包含 nullundefined 类型的函数,则会产生编译时错误。下面的callback 参数是可选的(注意?),所以它可能 undefined。因此,它不能被直接调用


function doSomething(callback?: () => void) { // Error: 不能调用可能是 “undefined” 的对象 callback(); }

与在访问属性之前检查对象类似,我们首先需要检查函数是否具有非空值:


function doSomething(callback?: () => void) { if (callback) { callback(); } }

还可以用 typeof 检查返回的值


function doSomething(callback?: () => void) { if (typeof callback === "function") { callback(); } }

总结

Non-nullable 类型是 TypeScript 类型系统的基础和有价值的补充。它们允许对哪些变量和属性可以为空进行精确构建。只有在类型保护将属性访问或函数调用确定为安全之后,才允许进行属性访问或函数调用,从而避免了许多编译时的可空性错误。

往期阅读

【TypeScript 进化史 — 破晓】一步一个脚印带你入门 TS
【TypeScript 进化史 — 1】non-nullable 的类型
【TypeScript 进化史 — 2】基于控制流的类型分析 和 只读属性
【TypeScript 进化史 — 3】标记联合类型 与 never 类型
【TypeScript 进化史 — 4】更多的字面量类型 与 内置类型声明
【TypeScript 进化史 — 5】将 async、await 编译到 ES3、ES5 (外部帮助库)
【TypeScript 进化史 — 6】对象扩展运算符和 rest 运算符及 keyof 和查找类型
【TypeScript 进化史 — 7】映射类型和更好的字面量类型推断
【TypeScript 进化史 — 8】字面量类型扩展 和 无类型导入
【TypeScript 进化史 — 9】object 类型 和 字符串索引签名类型的点属性
【TypeScript 进化史 — 10】更好的空值检查 和 混合类
【TypeScript 进化史 — 11】泛型参数默认类型 和 新的 –strict 编译选项

作者:Marius Schulz
译者:前端小智
链接:https://segmentfault.com/a/1190000020706641

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:【TypeScript 进化史 — 1】non-nullable 的类型

链接:https://www.javascriptc.com/3351.html

« 深入浅出 Serverless:优势、意义与应用 | GMTC
什么?都2020了console你还是只会log?»
Flutter 中文教程资源

相关推荐

QR code