详解TypeScript中的类型保护


Posted in Javascript onApril 29, 2021

概述

在 TypeScript 中使用联合类型时,往往会碰到这种尴尬的情况:

interface Bird {
  	// 独有方法
    fly();
  	// 共有方法
    layEggs();
}

interface Fish {
  	// 独有方法
    swim();
  	// 共有方法
    layEggs();
}

function getSmallPet(): Fish | Bird {
    // ...
}

let pet = getSmallPet();
pet.layEggs(); // 正常
pet.swim();    // ts 报错

如上所示,getSmallPet函数中,既可以返回 Fish 类型的对象,又可以返回 Bird 类型的对象。由于返回的对象类型不确定,所以使用联合类型对象共有的方法时,一切正常,但是使用联合类型对象各自独有的方法时,ts 会报错。

那么如何解决这个问题呢?最粗暴的方法当然是将联合类型转换为 any,不过这种方法不值得提倡,毕竟我们写的是 TypeScript 而不是 AnyScript。

此时,我们使用今天的主角——类型保护,闪亮登场,它可以完美的解决这个问题。

孔乙己说过,茴香豆有四种写法,同理,实现类型保护,也有四种写法。

类型断言

类型断言是最常用的一种类型保护方法,即直接指定类型。由于,TypeScript 中识别的类型大多是靠 TypeScript 的自动类型推算算出来的,所以会出现上面所说的那种问题,即 TypeScript 不知道具体对象类型是什么,所以不确定有没有联合类型各自独有的方法。

当使用类型断言直接指定类型时,相当于你让 TypeScript 开启了上帝模式,可以直接知道具体类型是联合类型中的那个,此时再使用对象的独有方法就符合 TypeScript 的推断了。

interface Bird {
  // 独有方法
  fly();
  // 共有方法
  layEggs();
}

interface Fish {
  // 独有方法
  swim();
  // 共有方法
  layEggs();
}

function getSmallPet(): Fish | Bird {
  // ...
}

let pet = getSmallPet();
pet.layEggs(); // 正常
// 通过鸭子类型来进行判断
if ((pet as Bird).fly) {
  // 类型断言
  (pet as Bird).fly()
} else {
  // 类型断言
  (pet as Fish).swim()
}

如果嫌弃通过 as 来进行类型断言不够上流,还可以使用类泛型的写法,即:

let pet = getSmallPet();
pet.layEggs(); // 正常
// 通过鸭子类型来进行判断
if ((<Bird>pet).fly) {
  (<Bird>pet).fly()
} else {
  (<Fish>pet).swim()
}

tips:友情提示,虽然使用类泛型写法进行类型断言看起来高端一些,但是由于在 tsx 中语法存在歧义,所以为了统一起见,推荐使用 as 的方法进行类型断言。

in语法

在js中,我们经常使用 in 语法来判断指定的属性是否在指定的对象或其原型链中。

同理,在 TypeScript 中,我们可以通过这种方法确认对象类型。

interface Bird {
  // 独有方法
  fly();
  // 共有方法
  layEggs();
}

interface Fish {
  // 独有方法
  swim();
  // 共有方法
  layEggs();
}

function getSmallPet(): Fish | Bird {
  // ...
}

let pet = getSmallPet();
pet.layEggs(); // 正常
// 使用 in 语法进行类型保护
if ('fly' in pet) {
  pet.fly()
} else {
  pet.swim()
}

原理同类型断言一样,都是引导 TypeScript 的类型推断,确定对象类型。

instanceof 语法

当联合类型中使用的是 class 而不是 interface 时,instanceof 语法就派上用场了,通过 instanceof 语法可以区分不同的 class 类型。

class Bird {
  // 独有方法
  fly() {};
  // 共有方法
  layEggs() {};
}

class Fish {
  // 独有方法
  swim() {};
  // 共有方法
  layEggs() {};
}

function getSmallPet(): Fish | Bird {
  // ...
}

let pet = getSmallPet();
pet.layEggs(); // 正常
// 使用 in 语法进行
if (pet instanceof Bird) {
  pet.fly()
} else {
  pet.swim()
}

typeof 语法

typeof 语法不同于 in 语法以及 instanceof 语法,in 语法以及 instanceof 语法都是用来引导类型推断进行不同对象类型推断,而 typeof 语法常用于基本类型的推断(或者是联合使用基本类型和对象类型)。

简而言之,当使用 typeof 能够区分联合类型中的不同类型时,即可使用它。

function getSmallPet(): number | string {
  // ...
}

let pet = getSmallPet();
if (typeof pet === 'number') {
  pet++
} else {
  pet = Number(pet) + 1
}

总结

就如茴香豆的四种写法的本质依然是茴香豆一样,类型保护的四种写法的本质也是一样的,即,引导 TypeScript 中的类型推断将类型推断的多选题变为单选题,这就是类型保护的本质。

以上就是详解TypeScript中的类型保护的详细内容,更多关于TypeScript类型保护的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
解决ExtJS在chrome或火狐中正常显示在ie中不显示的浏览器兼容问题
Jan 11 Javascript
js为鼠标添加右击事件防止默认的右击菜单弹出
Jul 29 Javascript
javascript中创建对象的几种方法总结
Nov 01 Javascript
JavaScript中实现无缝滚动、分享到侧边栏实例代码
Apr 06 Javascript
js html5 css俄罗斯方块游戏再现
Oct 17 Javascript
el表达式 写入bootstrap表格数据页面的实例代码
Jan 11 Javascript
解析Vue2.0双向绑定实现原理
Feb 23 Javascript
jQuery使用DataTable实现删除数据后重新加载功能
Feb 27 Javascript
详解vue-cli快速构建项目以及引入bootstrap、jq
May 26 Javascript
JS写XSS cookie stealer来窃取密码的步骤详解
Nov 20 Javascript
JavaScript Array对象使用方法解析
Sep 24 Javascript
JavaScript实现打砖块游戏
Feb 25 Javascript
7个你应该知道的JS原生错误类型
Apr 29 #Javascript
使用vue-element-admin框架从后端动态获取菜单功能的实现
如何使用JavaScript策略模式校验表单
Apr 29 #Javascript
react中props 的使用及进行限制的方法
Apr 28 #Javascript
React Hook用法示例详解(6个常见hook)
vue使用v-model进行跨组件绑定的基本实现方法
为什么node.js不适合大型项目
You might like
PHP字符转义相关函数小结(php下的转义字符串)
2007/04/12 PHP
php 验证码实例代码
2010/06/01 PHP
Zend Framework教程之Autoloading用法详解
2016/03/08 PHP
PHP指定截取字符串中的中英文或数字字符的实例分享
2016/03/18 PHP
PHP基于堆栈实现的高级计算器功能示例
2017/09/15 PHP
捕获关闭窗口的脚本
2009/01/10 Javascript
客户端限制只能上传jpg格式图片的js代码
2010/12/09 Javascript
Jqgrid表格随窗口大小改变而改变的简单实例
2013/12/28 Javascript
防止jQuery ajax Load使用缓存的方法小结
2014/02/22 Javascript
jQuery添加/改变/移除CSS类及判断是否已经存在CSS
2014/08/20 Javascript
node.js中的buffer.fill方法使用说明
2014/12/14 Javascript
js改变embed标签src值的方法
2015/04/10 Javascript
js调用百度地图及调用百度地图的搜索功能
2015/09/07 Javascript
Javascript设计模式之观察者模式(推荐)
2016/03/29 Javascript
Bootstrap基本样式学习笔记之表格(2)
2016/12/07 Javascript
Bootstrap Paginator+PageHelper实现分页效果
2018/12/29 Javascript
微信小程序开发的基本流程步骤
2019/01/31 Javascript
JS栈stack类的实现与使用方法示例
2019/01/31 Javascript
js的继承方法小结(prototype、call、apply)(推荐)
2019/04/17 Javascript
js简单遍历获取对象中的属性值的方法示例
2019/06/19 Javascript
微信小程序如何获取群聊的openGid以及名称详解
2019/07/17 Javascript
jQuery实现的上拉刷新功能组件示例
2020/05/01 jQuery
详解JavaScript中的this指向问题
2021/02/05 Javascript
js面向对象封装级联下拉菜单列表的实现步骤
2021/02/08 Javascript
python实现的防DDoS脚本
2011/02/08 Python
python sort、sorted高级排序技巧
2014/11/21 Python
在Django框架中设置语言偏好的教程
2015/07/27 Python
Python递归函数实例讲解
2019/02/27 Python
django最快程序开发流程详解
2019/07/19 Python
Python爬取视频(其实是一篇福利)过程解析
2019/08/01 Python
详解Anaconda 的安装教程
2020/09/23 Python
台湾7-ELEVEN线上购物中心:7-11
2021/01/21 全球购物
JAVA软件工程师测试题
2014/07/25 面试题
总经理助理岗位职责
2013/11/08 职场文书
2015年学校食堂工作总结
2015/04/22 职场文书
html+css实现滚动到元素位置显示加载动画效果
2021/08/02 HTML / CSS