浅谈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 相关文章推荐
javascript读取xml
Nov 04 Javascript
JavaScript的null和undefined区别示例介绍
Sep 15 Javascript
jquery实现键盘左右翻页特效
Apr 30 Javascript
jQuery移动web开发中的页面初始化与加载事件
Dec 03 Javascript
JS DOM实现鼠标滑动图片效果
Sep 17 Javascript
jQuery简单实现title提示效果示例
Aug 01 Javascript
JavaScript表单验证完美代码
Mar 02 Javascript
微信小程序 合法域名校验出错详解及解决办法
Mar 09 Javascript
react实现菜单权限控制的方法
Dec 11 Javascript
详解Angular系列之变化检测(Change Detection)
Feb 26 Javascript
Angular中使用better-scroll插件的方法
Mar 27 Javascript
搭建vscode+vue环境的详细教程
Aug 31 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 利用AJAX获取网页并输出的实现代码(Zjmainstay)
2012/08/31 PHP
PHP将两个关联数组合并函数提高函数效率
2014/03/18 PHP
php中filter_input函数用法分析
2014/11/15 PHP
Zend Framework教程之Zend_Db_Table_Row用法实例分析
2016/03/21 PHP
Laravel5中Cookie的使用详解
2017/05/03 PHP
javascript中的变量是传值还是传址的?
2010/04/19 Javascript
javascript检测浏览器flash版本的实现代码
2011/12/06 Javascript
JSON+JavaScript处理JSON的简单例子
2013/03/20 Javascript
JS 加入收藏夹的代码(主流浏览器通用)
2013/05/13 Javascript
Jquery实现兼容各大浏览器的Enter回车切换输入焦点的方法
2014/09/01 Javascript
第三篇Bootstrap网格基础
2016/06/21 Javascript
JS实现图片上传预览功能
2016/11/21 Javascript
实例分析nodejs模块xml2js解析xml过程中遇到的坑
2017/03/18 NodeJs
Angular4学习笔记之实现绑定和分包
2017/08/01 Javascript
JS设计模式之访问者模式定义与用法分析
2018/02/05 Javascript
js实现多个倒计时并行 js拼团倒计时
2019/02/25 Javascript
vue3 源码解读之 time slicing的使用方法
2019/10/31 Javascript
详解微信小程序动画Animation执行过程
2020/09/23 Javascript
ES5和ES6中类的区别总结
2020/12/21 Javascript
Python数据结构与算法之完全树与最小堆实例
2017/12/13 Python
Python自定义简单图轴简单实例
2018/01/08 Python
解决Python print 输出文本显示 gbk 编码错误问题
2018/07/13 Python
深入理解Python中的 __new__ 和 __init__及区别介绍
2018/09/17 Python
Python实现字符串中某个字母的替代功能
2019/10/21 Python
Python的几种主动结束程序方式
2019/11/22 Python
Python如何使用OS模块调用cmd
2020/02/27 Python
JD Sports马来西亚:英国领先的运动鞋和运动服饰零售商
2018/03/13 全球购物
this关键字的作用
2016/01/30 面试题
机械制造与自动化应届生求职信
2013/11/16 职场文书
化工专业个人的求职信范文
2013/11/28 职场文书
会计专业应届生自荐信
2014/02/07 职场文书
乡镇干部先进性教育活动个人整改措施
2014/09/16 职场文书
离婚协议书怎么写的
2014/12/14 职场文书
邀请函模板
2015/02/02 职场文书
车间质检员岗位职责
2015/04/08 职场文书
Java各种比较对象的方式的对比总结
2021/06/20 Java/Android