浅谈TypeScript的类型保护机制


Posted in Javascript onFebruary 23, 2020

在编写 TS 时,它做了比我们看到的更多的事情,例如类型保护机制。让我们编写的代码更加严谨,至于怎么回事,让我们来看看吧。

由于这些机制的存在,就算你仍旧以 JS 原生的书写方式,也能帮助你提前发现代码中潜在的问题。(对于认为 TS 语句更复杂的人,也能实现 0 门槛,不改变已有的习惯也能享受静态检测的好处。)

类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域内的类型。

为了更简单的理解,我们首先声明一个联合类型用于举例:

interface Bird {
 fly(): any;
 layEggs(): any;
}

interface Fish {
 swim(): any
 layEggs(): any
}

type Pet = Bird | Fish;

无类型保护时报错

function fn(pet: Pet) { 
 pet.layEggs(); // okay
 pet.swim();  // Error: Property 'swim' does not exist on type 'Bird | Fish'.
}

因为 TS 并不知道 pet 的实例是 Bird 还是 Fish,因此为了谨慎起见,在未手动声明类型时 TS 中只能调用 联合类型 中的 公共方法,例子中未 layEggs() 方法。除非你在调用指定对象数据的属性或方法前,明确告诉 TS 数据对象是一个具体的类型。

类型断言实现类型保护

我需要使用 <Fish>pet 的 类型断言,来告诉 TS 目标对象是什么类型:

function fn(pet: Fish | Bird) {
 if ((<Fish>pet).swim) {
  (<Fish>pet).swim();
 } else {
  (<Bird>pet).fly();
 }
}

虽然这样的断言满足了我们的需求,但并不好方便,需要在各处都进行引用。
备注:如果在编写 tsx 时,你需要将 (<Fish>pet) 写成 (pet as Fish),因为在 tsx 中尖括号 <> 有特殊的含义。

函数中使用 is 定位类型

我们将上面的 if 内的判断封装到函数中,获得更方便的类型保护方式,此函数必须使用 parameterName is Type 的 类型谓语:

function isFish<T>(pet: Fish | Bird): pet is Fish {
 return !!(<Fish>pet).swim;
}

此函数必须返回为 boolean 类型才生效,当返回 true 时则类型定位为 Fish ,返回 false 时则定位为 Fish 之外的类型(多个类型则以 联合类型 定位)。

function fn(pet: Fish | Bird ) { 
 if (isFish(pet)) {
  pet.swim(); // 因 is 语句的生效,此语句块中类型 let pet: Fish
 } else {
  pet.fly(); // 排除 Fish 之外的类型,此语句块中类型 let pet: Bird
 }
}

需要注意是除了 if 中类型生效,TS 还能自动推断出 else 中的类型。

就算你不使用 TS 这些特定的语句,也能享受 类型保护机制 的好处,下面让我们来看看。

使用 typeof 进行类型保护

如果子类型是只是 number、string、boolean、symbol 这几种数据类型,则可以直接使用 typeof 关键字,TS 能够检测并提供类型保护,我们直接引用官方给的例子:

function padLeft(value, padding): string {
  if (typeof padding === "number") {
    return Array(padding + 1).join(" ") + value;  // let padding: number
  }
  else {
    return padding + value;  // let padding: string
  }
}
  
const t1 = padLeft("world", 6);    // "   world"
const t2 = padLeft("world", "hello "); // "hello world"

使用 instanceof 进行类型保护

由于现在前端对于 面向对象 的开发项目越来越多,因此类的引用也更多了。那么类型保护用在此时,可谓是更加有重要,我们使用 instanceof 来达到这一效果:

interface IA { x(): void; }
interface IB { y(): void; }

class A implements IA {
 x() { }
}
class B implements IB {
 y() { }
}

function fn(e: A | B) {
 if (e instanceof A)
  e.x(); // let e: A
 else
  e.y(); // let e: 
}

基于类型保护机制,在语句块中编辑器会给予指定类型的 方法提示,以及类型检测时会提示用户。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery EasyUI API 中文文档 DateTimeBox日期时间框
Oct 16 Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
Dec 11 Javascript
一行代码告别document.getElementById
Jun 01 Javascript
Jquery的each里用return true或false代替break或continue
May 21 Javascript
浅析JQuery中的html(),text(),val()区别
Sep 01 Javascript
5个JavaScript经典面试题
Oct 13 Javascript
使用jQuery在对象中缓存选择器的简单方法
Jun 30 Javascript
JQuery ztree带筛选、异步加载实例讲解
Feb 25 Javascript
JavaScript数据类型转换的注意事项
Jul 31 Javascript
Gulp实现静态网页模块化的方法详解
Jan 09 Javascript
JS数组方法reverse()用法实例分析
Jan 18 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
Mar 08 Javascript
原生javascript制作的拼图游戏实现方法详解
Feb 23 #Javascript
原生javascript运动函数的封装示例【匀速、抛物线、多属性的运动等】
Feb 23 #Javascript
es6中Promise 对象基本功能与用法实例分析
Feb 23 #Javascript
原生JavaScript之es6中Class的用法分析
Feb 23 #Javascript
原生javascript单例模式的应用实例分析
Feb 23 #Javascript
小程序websocket心跳库(websocket-heartbeat-miniprogram)
Feb 23 #Javascript
webpack.DefinePlugin与cross-env区别详解
Feb 23 #Javascript
You might like
php防注
2007/01/15 PHP
php语言流程控制中的主动与被动
2012/11/05 PHP
正确的PHP匹配UTF-8中文的正则表达式
2015/05/13 PHP
Zend Framework校验器Zend_Validate用法详解
2016/12/09 PHP
DOM 基本方法
2009/07/18 Javascript
node.js chat程序如何实现Ajax long-polling长链接刷新模式
2012/03/13 Javascript
JavaScript异步调用定时方法并停止该方法实现代码
2012/03/16 Javascript
被遗忘的javascript的slice() 方法
2015/04/20 Javascript
js实现键盘Enter键提交表单的方法
2015/05/27 Javascript
JavaScript函数学习总结以及相关的编程习惯指南
2015/11/16 Javascript
最丑的时钟效果!js canvas时钟制作方法
2016/08/15 Javascript
jQuery监听文件上传实现进度条效果的方法
2016/10/16 Javascript
浅谈js数组和splice的用法
2016/12/04 Javascript
webpack入门必知必会
2017/01/16 Javascript
防止重复发送 Ajax 请求
2017/02/15 Javascript
微信小程序 密码输入(源码下载)
2017/06/27 Javascript
Node 自动化部署的方法
2017/10/17 Javascript
jquery中有哪些api jQuery主要API
2017/11/20 jQuery
微信小程序支付及退款流程详解
2017/11/30 Javascript
JavaScript EventEmitter 背后的秘密 完整版
2018/03/29 Javascript
详解VUE项目中安装和使用vant组件
2019/04/28 Javascript
react quill中图片上传由默认转成base64改成上传到服务器的方法
2019/10/30 Javascript
微信小程序 flexbox layout快速实现基本布局的解决方案
2020/03/24 Javascript
Vue-cli打包后部署到子目录下的路径问题说明
2020/09/02 Javascript
python中管道用法入门实例
2015/06/04 Python
Python面向对象编程之继承与多态详解
2018/01/16 Python
Python Pandas 转换unix时间戳方式
2019/12/07 Python
matplotlib绘制鼠标的十字光标的实现(内置方式)
2021/01/06 Python
HTML5的结构和语义(4):语义性的内联元素
2008/10/17 HTML / CSS
世界上最好的威士忌和烈性酒购买网站:The Whisky Exchange
2016/11/20 全球购物
美国演唱会和体育门票购买网站:Ticketnetwork
2018/10/19 全球购物
学生感冒英文请假条
2014/02/04 职场文书
户外宣传策划方案
2014/05/25 职场文书
初中生思想道德自我评价
2015/03/09 职场文书
SpringMVC 整合SSM框架详解
2021/08/30 Java/Android
Pytorch中使用ImageFolder读取数据集时忽略特定文件
2022/03/23 Python