前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >作为JavaScript的“超集”,感受一下TypeScript 的那些黑魔法

作为JavaScript的“超集”,感受一下TypeScript 的那些黑魔法

作者头像
博文视点Broadview
发布2020-06-12 09:10:41
1K0
发布2020-06-12 09:10:41
举报
文章被收录于专栏:博文视点Broadview

// TypeScript 是JavaScript的“超集” //

// 前端语言中冉冉升起的新星 //

TypeScript是一种由微软开发的、开源的编程语言,近两年发展迅猛,越来越多的JavaScript项目正在迁移到TypeScript,主流前端框架及Node.js对TypeScript的支持也越来越友好。自2012年10月发布首个公开版本以来,它已得到了人们的广泛认可。

TypeScript发展至今,已经成为很多大型项目的标配,其提供的静态类型系统,大大增强了代码的可读性及可维护性;同时,它提供最新的和不断发展的JavaScript特性,能让我们构建更健壮的组件。

然而在TypeScript中,有些地方对“开箱即用”进行了限制,例如当使用一个未被声明过的变量时(当然,你可以为外部系统使用声明文件)。也就是说,传统的编程语言在类型系统允许与不允许之间存在明显的边界。

TypeScript不同于传统的编程语言,它可以让你自己设置类型系统的边界。这实际上是为了让你能够使用你喜欢的JavaScript,并尽可能安全地使用它。

在TypeScript中,有很多选项都可以精确地控制此边界,下文选自《深入理解TypeScript》一书,现在就让我们去了解它们吧。

▼▼▼

选项为boolean的compilerOptions,可以被指定为tsconfig.json下的compilerOptions。

代码语言:javascript
复制
1{
2    "compilerOptions": {
3        "someBooleanOption": true
4    }
5}

或者使用命令行。

代码语言:javascript
复制
1tsc --someBooleanOption

所有这些选项的默认设置都是false。

▼▼▼

有些代码无法被推断,或者推断它们可能会导致意外的错误。一个很好的例子就是函数参数,如果没有对它们进行注解,那么你将不清楚哪些是有效的。

代码语言:javascript
复制
1functionlog(someArg) {
2    sendDataToServer(someArg);
3}
4// 参数是什么,下面哪个是不正确的
5log(123);
6log('hello world'); 

因此,如果你没有注解函数的参数,TypeScript将会认为它是any类型的,并将继续执行。在这种情况下,将会关闭类型检查,这是JavaScript开发人员所期望的。但是这可能会让那些对安全性要求较高的人措手不及。因此,这里有一个noImplicitAny选项,当开启这个选项时,它将会标记无法被推断的类型的情况,如下所示。

代码语言:javascript
复制
1functionlog(someArg) {// 错误:someArg是any类型的
2    sendDataToServer(someArg);
3}

当然,你可以继续进行注解。

代码语言:javascript
复制
1functionlog(someArg: number) {
2    sendDataToServer(someArg);
3} 

如果真的想抛弃安全性,你可以把它标记为any。

代码语言:javascript
复制
1functionlog(someArg: any) {
2    sendDataToServer(someArg);
3} 

▼▼▼

在默认情况下,null和undefined可以被赋值给TypeScript中的所有类型。

代码语言:javascript
复制
1let foo: number = 123;
2foo = null;        // 可以
3foo = undefined; // 可以

这顺应了大多数编写JavaScript的人的习惯。但是,同时TypeScript允许你明确指出可以分配给null/undefined的内容。

在严格的null检查模式下,null和undefined是不同的。

代码语言:javascript
复制
1let foo = undefined;
2foo = null;        // 不可以 
代码语言:javascript
复制

假设有一个接口Member,如下所示。

代码语言:javascript
复制
1interface Member {
2    name: string,
3    age?: number
4}

并不是所有的Member都会提供年龄,所以age是一个可选属性,也就是说age的值可能为undefined。

undefined是“万恶之源”,它通常会导致运行时错误。(编写在运行时抛出错误的代码很容易。)

代码语言:javascript
复制
1getMember()
2  .then(member: Member =>{
3    conststringifyAge = member.age.toString()
4
5                //toString属性可能undefined
6  }) 

但是在严格的null检查模式下,这个错误将会在编译时被捕获。

代码语言:javascript
复制
1getMember()
2  .then(member: Member =>{
3    conststringifyAge = member.age.toString() // 对象可能undefined
4  }) 

◆ 非空断言操作符

在一个类型检查无法得出结论的上下文中,一个新的!表达式后缀操作符,可以用来断言运算对象是非null和非undefined的,示例如下。

代码语言:javascript
复制
 1     // 用--strictNullChecks进行编译
 2functionvalidateEntity(e?:  Entity) {
 3     // 如果e是null或其他无效的实体,则抛出错误
 4}
 5
 6functionprocessEntity(e?: Entity) {
 7    validateEntity(e);
 8    let a = e.name;        // 错误:e可能是null
 9    let b = e!.name;       // 可以,我们已经断言e是非null
10} 

注意,它只是一个断言,就像类型断言一样,你需要确保该值不为空。一个非null的断言实质上意味着你在告诉编译器“我知道它不是null,但是请让我使用它,即使它不是null”。

◆ 明确赋值断言操作符

TypeScript将会对类中未初始化的属性抛出错误。

代码语言:javascript
复制
 1class C {
 2  foo: number;                  // 可以,已经在构造器中初始化
 3  bar: string = "hello";      // 可以,已经初始化
 4  baz: boolean;               
 5
 6// 错误:属性baz没有初始化,也没有在构造器中被赋值
 7  constructor() {
 8    this.foo = 42;
 9  }
10} 

你可以使用明确赋值断言,在属性名后加后缀,来告诉TypeScript你已经在其他地方(不是在构造器中)对它进行了初始化。

代码语言:javascript
复制
 1class C {
 2  foo!: number;           // 注意这个感叹号
 3                               // 这是明确赋值断言操作符
 4
 5  constructor() {
 6    this.initialize();
 7  }
 8  initialize() {
 9    this.foo = 0;
10  }
11} 

你也可以将此操作符与变量声明一起使用。

代码语言:javascript
复制
 1let a: number[];           // 没有断言
 2let b!: number[];             // 断言
 3
 4initialize();
 5
 6a.push(4);                   // 错误:变量在赋值之前被使用
 7b.push(4);                   // 可以:因为被断言
 8
 9functioninitialize() {
10    a = [0,1,2,3];
11    b = [0,1,2,3];
12} 

就像所有的断言一样,你在告诉编译器让它相信你,让编译器不再抛出错误,即使代码并没有被分配属性。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 博文视点Broadview 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档