浅谈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的访问WebService的代码(可访问Java[Xfire])
Nov 19 Javascript
Javascript面向对象扩展库代码分享
Mar 27 Javascript
javascript字符串替换及字符串分割示例代码
Dec 12 Javascript
JS+CSS实现分类动态选择及移动功能效果代码
Oct 19 Javascript
JS组件Bootstrap实现下拉菜单效果代码
Apr 26 Javascript
微信小程序-详解数据缓存
Nov 24 Javascript
input框中自动展示当前日期yyyy/mm/dd的实现方法
Jul 06 Javascript
轻量级JS Cookie插件js-cookie的使用方法
Mar 22 Javascript
解决vue 格式化银行卡(信用卡)每4位一个符号隔断的问题
Sep 14 Javascript
关于在LayUI中使用AJAX提交巨坑记录
Oct 25 Javascript
Vue3 的响应式和以前有什么区别,Proxy 无敌?
May 20 Javascript
jQuery中getJSON跨域原理的深入讲解
Sep 02 jQuery
原生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设计模式之装饰器(装饰者)模式(Decorator)入门与应用详解
2019/12/13 PHP
Javascript的闭包
2009/12/31 Javascript
jQuery-Tools-overlay 使用介绍
2012/07/14 Javascript
js实现div弹出层的方法
2014/11/20 Javascript
JavaScript通过join函数连接数组里所有元素的方法
2015/03/20 Javascript
浅谈JavaScript异常处理语句
2015/06/26 Javascript
JS模仿手机端九宫格登录功能实现代码
2016/04/28 Javascript
深入理解js数组的sort排序
2016/05/28 Javascript
javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】
2016/12/15 Javascript
JS中使用 after 伪类清除浮动实例
2017/03/01 Javascript
js中setTimeout的妙用--防止循环超时
2017/03/06 Javascript
原生js实现简单的Ripple按钮实例代码
2017/03/24 Javascript
JavaScript表单即时验证 验证不成功不能提交
2017/08/31 Javascript
[25:45]2018DOTA2亚洲邀请赛4.5SOLO赛 Sylar vs Paparazi
2018/04/06 DOTA
python获取Linux下文件版本信息、公司名和产品名的方法
2014/10/05 Python
在Python中使用Neo4j数据库的教程
2015/04/16 Python
深入解析Python中的变量和赋值运算符
2015/10/12 Python
Python实现Linux中的du命令
2017/06/12 Python
python实现数据图表
2017/07/29 Python
解读python logging模块的使用方法
2018/04/17 Python
Python闭包函数定义与用法分析
2018/07/20 Python
flask框架jinja2模板与模板继承实例分析
2019/08/01 Python
python脚本调用iftop 统计业务应用流量的思路详解
2019/10/11 Python
python学生信息管理系统实现代码
2019/12/17 Python
最新2019Pycharm安装教程 亲测
2020/02/28 Python
如何通过命令行进入python
2020/07/06 Python
利用CSS3 动画 绘画 圆形动态时钟
2018/03/20 HTML / CSS
Ray-Ban雷朋美国官网:全球领先的太阳眼镜品牌
2016/07/20 全球购物
英国Boots旗下太阳镜网站:Boots Designer Sunglasses
2018/07/07 全球购物
英国家用电器折扣网站:Electrical Discount UK
2018/09/17 全球购物
全球工业:Global Industrial
2020/02/01 全球购物
市场部经理岗位职责
2014/04/10 职场文书
大学竞选班长演讲稿
2014/04/24 职场文书
财务工作失职检讨书
2014/11/21 职场文书
2015年调度员工作总结
2015/04/30 职场文书
2019毕业论文致谢词
2019/06/24 职场文书