浅谈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记住用户名和密码的具体实现
Apr 04 Javascript
详细解读JavaScript编程中的Promise使用
Jul 27 Javascript
简介alert()与console.log()的不同
Aug 26 Javascript
移动端使用localStorage缓存Js和css文的方法(web开发)
Sep 20 Javascript
干货!教大家如何选择Vue和React
Mar 13 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
Apr 07 Javascript
详谈AngularJs 控制器、数据绑定、作用域
Jul 09 Javascript
vue项目中应用ueditor自定义上传按钮功能
Apr 27 Javascript
Vue中的vue-resource示例详解
Nov 02 Javascript
Vue.js 中的 v-cloak 指令及使用详解
Nov 19 Javascript
bootstrap下拉分页样式 带跳转页码
Dec 29 Javascript
基于JS+HTML实现弹窗提示是否确认提交功能
Jun 17 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版
2006/10/09 PHP
php使用pdo连接sqlite3的配置示例
2016/05/27 PHP
PHP中str_split()函数的用法讲解
2019/04/11 PHP
用JS实现一个页面多个css样式实现
2008/05/29 Javascript
jQuery建立一个按字母顺序排列的友好页面索引(兼容IE6/7/8)
2013/02/26 Javascript
PHPMyAdmin导入时提示文件大小超出PHP限制的解决方法
2015/03/30 Javascript
js根据手机客户端浏览器类型,判断跳转官网/手机网站多个实例代码
2016/04/30 Javascript
js实现canvas保存图片为png格式并下载到本地的方法
2017/08/31 Javascript
vue使用drag与drop实现拖拽的示例代码
2017/09/07 Javascript
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
2017/11/20 Javascript
Vue通过URL传参如何控制全局console.log的开关详解
2017/12/07 Javascript
vue路由组件按需加载的几种方法小结
2018/07/12 Javascript
this在vue和小程序中的使用详解
2019/01/28 Javascript
JavaScript中的事件与异常捕获详析
2019/02/24 Javascript
jquery操作select常见方法大全【7种情况】
2019/05/28 jQuery
JS数组splice操作实例分析
2019/10/12 Javascript
js实现多图和单图上传显示
2019/12/18 Javascript
js cavans实现静态滚动弹幕
2020/05/21 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
JavaScript中的函数式编程详解
2020/08/22 Javascript
Django在Win7下的安装及创建项目hello word简明教程
2014/07/14 Python
Python smtplib实现发送邮件功能
2018/05/22 Python
python版本单链表实现代码
2018/09/28 Python
详解Python 函数如何重载?
2019/04/23 Python
django 多对多表的创建和插入代码实现
2019/09/09 Python
python 回溯法模板详解
2020/02/26 Python
白宫黑市官网:White House Black Market
2016/11/17 全球购物
Manduka官网:瑜伽垫、瑜伽毛巾和服装
2018/07/02 全球购物
超市促销实习自我鉴定
2013/09/23 职场文书
八年级数学教学反思
2014/01/31 职场文书
建筑施工安全责任书
2014/07/24 职场文书
法学专业求职信范文
2015/03/19 职场文书
婚礼家长致辞
2015/07/27 职场文书
互联网创业商业模式以及赚钱法则有哪些?
2019/10/12 职场文书
Python matplotlib多个子图绘制整合
2022/04/13 Python
nginx rewrite功能使用场景分析
2022/05/30 Servers