浅谈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 miniui 教程 表格控件 合并单元格应用
Nov 25 Javascript
jquery 多行文本框(textarea)高度变化
Jul 03 Javascript
基于编写jQuery的无缝滚动插件
Aug 02 Javascript
WordPress 单页面上一页下一页的实现方法【附代码】
Mar 10 Javascript
JS组件Bootstrap Table布局详解
May 27 Javascript
Bootstrap插件全集
Jul 18 Javascript
浅谈js中startsWith 函数不能在任何浏览器兼容的问题
Mar 01 Javascript
JavaScript中in和hasOwnProperty区别详解
Aug 04 Javascript
Vue.js如何实现路由懒加载浅析
Aug 14 Javascript
解决vue初始化项目时,一直卡在Project description上的问题
Oct 31 Javascript
JavaScript中常用的3种弹出提示框(alert、confirm、prompt)
Nov 10 Javascript
如何在CocosCreator里画个炫酷的雷达图
Apr 16 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网页游戏学习之Xnova(ogame)源码解读(九)
2014/06/24 PHP
php模仿asp Application对象在线人数统计实现方法
2015/01/04 PHP
php从数组中随机选择若干不重复元素的方法
2015/03/14 PHP
php检查字符串中是否有外链的方法
2015/07/29 PHP
thinkPHP导出csv文件及用表格输出excel的方法
2015/12/30 PHP
PHP的Laravel框架中使用消息队列queue及异步队列的方法
2016/03/21 PHP
Fleaphp常见函数功能与用法示例
2016/11/15 PHP
laravel框架 laravel-admin上传图片到oss的方法
2019/10/13 PHP
JavaScript中的对象化编程
2008/01/16 Javascript
js鼠标左右键 键盘值小结
2010/06/11 Javascript
JS实现可拖曳、可关闭的弹窗效果
2015/09/26 Javascript
详解JavaScript中双等号引起的隐性类型转换
2016/05/30 Javascript
浅谈Vue.js应用的四种AJAX请求数据模式
2017/08/30 Javascript
如何将你的AngularJS1.x应用迁移至React的方法
2018/02/01 Javascript
JS实现textarea通过换行或者回车把多行数字分割成数组并且去掉数组中空的值
2018/10/29 Javascript
Vue响应式原理Observer、Dep、Watcher理解
2019/06/06 Javascript
原生JS无缝滑动轮播图
2019/10/22 Javascript
vue element-ui实现动态面包屑导航
2019/12/23 Javascript
Vue过渡效果之CSS过渡详解(结合transition,animation,animate.css)
2020/02/05 Javascript
Vue的Options用法说明
2020/08/14 Javascript
OpenLayers3实现测量功能
2020/09/25 Javascript
[04:26]2014DOTA2国际邀请赛-Newbee顺利进入胜者组决赛 独家专访战神7
2014/07/19 DOTA
[01:11:32]VG vs FNATIC 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
django实现分页的方法
2015/05/26 Python
各种Python库安装包下载地址与安装过程详细介绍(Windows版)
2016/11/02 Python
Python基于回溯法子集树模板解决m着色问题示例
2017/09/07 Python
使用python爬虫实现网络股票信息爬取的demo
2018/01/05 Python
django中使用事务及接入支付宝支付功能
2019/09/15 Python
python3中TQDM库安装及使用详解
2020/11/18 Python
几道PHP的面试题
2012/05/19 面试题
销售心得体会
2014/01/02 职场文书
《孔繁森》教学反思
2014/04/17 职场文书
新品发布会策划方案
2014/06/08 职场文书
幼儿教师小班个人总结
2015/02/05 职场文书
MySQL 可扩展设计的基本原则
2021/05/14 MySQL
Java并发编程之Executor接口的使用
2021/06/21 Java/Android