浅谈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 相关文章推荐
JS记录用户登录次数实现代码
Jan 15 Javascript
js用Date对象的setDate()函数对日期进行加减操作
Sep 18 Javascript
AngularJS实现分页显示数据库信息
Jul 01 Javascript
js 弹出对话框(遮罩)透明,可拖动的简单实例
Jul 11 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐二)
Jul 12 Javascript
分分钟玩转Vue.js组件(二)
Mar 01 Javascript
js中如何完美的解析数据
Mar 18 Javascript
vue下拉列表功能实例代码
Apr 08 Javascript
Vue官方推荐AJAX组件axios.js使用方法详解与API
Oct 09 Javascript
react 中父组件与子组件双向绑定问题
May 20 Javascript
JS实现移动端点击按钮复制文本内容
Jul 28 Javascript
antd vue 刷新保留当前页面路由,保留选中菜单,保留menu选中操作
Aug 06 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 万年历实现代码
2012/10/18 PHP
thinkphp下MySQL数据库读写分离代码剖析
2017/04/18 PHP
PHP大文件分割上传 PHP分片上传
2017/08/28 PHP
PHP实现生成模糊图片的方法示例
2017/12/21 PHP
php PDO属性设置与操作方法分析
2018/12/27 PHP
jQuery 行背景颜色的交替显示(隔行变色)实现代码
2009/12/13 Javascript
js判断当前浏览器类型,判断IE浏览器方法
2014/06/02 Javascript
jQuery 和 CSS 的文本特效插件集锦
2014/12/12 Javascript
基于jQuery实现仿淘宝套餐选择插件
2015/03/04 Javascript
jQuery实现锚点scoll效果实例分析
2015/03/10 Javascript
详解Angular2中的编程对象Observable
2016/09/17 Javascript
JS跨域请求外部服务器的资源
2017/02/06 Javascript
bootstrap table表格插件使用详解
2017/05/08 Javascript
简单的React SSR服务器渲染实现
2018/12/11 Javascript
ES6基础之展开语法(Spread syntax)
2019/02/21 Javascript
vue读取本地的excel文件并显示在网页上方法示例
2019/05/29 Javascript
Vue 2.0 侦听器 watch属性代码详解
2019/06/19 Javascript
vue实现登录页面的验证码以及验证过程解析(面向新手)
2019/08/02 Javascript
对layui中的onevent 和event的使用详解
2019/09/06 Javascript
layUI的验证码功能及校验实例
2019/10/25 Javascript
序列化模块json代码实例详解
2020/03/03 Javascript
微信小程序使用GoEasy实现websocket实时通讯
2020/05/19 Javascript
微信小程序实现首页弹出广告
2020/12/03 Javascript
[01:36]极致酷炫!TI9典藏宝瓶+撼地者至宝展示
2019/06/11 DOTA
[01:03:41]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第三场 2月2日
2021/03/11 DOTA
Python实现树的先序、中序、后序排序算法示例
2017/06/23 Python
python实现感知器
2017/12/19 Python
Python设计模式之中介模式简单示例
2018/01/09 Python
Python实现Pig Latin小游戏实例代码
2018/02/02 Python
Tensorflow tf.dynamic_partition矩阵拆分示例(Python3)
2020/02/07 Python
Python Tkinter Entry和Text的添加与使用详解
2020/03/04 Python
详解pandas中iloc, loc和ix的区别和联系
2020/03/09 Python
党风廉政承诺书
2014/03/27 职场文书
学校捐款活动总结
2015/05/09 职场文书
CSS3 制作的图片滚动效果
2021/04/14 HTML / CSS
面试必问:圣杯布局和双飞翼布局的区别
2021/05/13 HTML / CSS