浅谈TypeScript的类型保护机制

在编写 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:
}

基于类型保护机制,在语句块中编辑器会给予指定类型的 方法提示,以及类型检测时会提示用户。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • TypeScript类型声明书写详解

    本文总结一下TypeScript类型声明的书写,很多时候写TypeScript不是问题,写类型就特别纠结,我总结下,我在使用TypeScript中遇到的问题.如果你遇到类型声明不会写的时候,多看看lodash的声明,因为lodash对数据进行各种变形操作,所以你能遇到的,都有参考示例. 基本类型 // 变量 const num: number = 1; const str: string = 'str'; const bool: boolean = true; const nulls: null

  • TypeScript入门-基本数据类型

    大致介绍 TypeScript是由C#语言之父Anders Hejlsberg主导开发的一门编程语言,TypeScript本质上是向JavaScript语言添加了可选的静态类型和基于类的面向对象编程,它相当于是JavaScript的超集 ES5.ES6和TypeScript的关系: 安装 首先需要安装npm,然后在输入 npm install -g typescript 安装完成后,因为TypeScript是以.ts结尾的,要想运行就得把他编译js文件,编译的方法特别简单就是使用tsc命令 ts

  • TypeScript Type Innference(类型判断)

    TypeScript 是微软开发的 JavaScript 的超集,TypeScript兼容JavaScript,可以载入JavaScript代码然后运行.TypeScript与JavaScript相比进步的地方 包括:加入注释,让编译器理解所支持的对象和函数,编译器会移除注释,不会增加开销:增加一个完整的类结构,使之更新是传统的面向对象语言. 为什么会有 TypeScript? JavaScript 只是一个脚本语言,并非设计用于开发大型 Web 应用,JavaScript 没有提供类和模块的概

  • TypeScript学习之强制类型的转换

    前言 使用强类型变量常常需要从一种类型向另一种类型转换,通常使用ToString或ParseInt可以来实现一些简单的转换,但是有时候需要像.NET语言中那样将一种类型显示的转换为另一种类型,在TypeScript规范中,被称为"类型断言",它仍然是类型转换,只是语法是有些不同.下面来详细看看TypeScript的强制类型转换. TypeScript强制类型转换 在 TypeScript 中将一个 number 转换成 string ,这样做会报错: var a:number = 12

  • TypeScript 学习笔记之基本类型

    在 TypeScript 中一共有 7 种基本类型. 1.boolean 复制代码 代码如下: var isDone: boolean = false; 2.number 代表 JavaScript 中的数字.在 JavaScript 中,无论是"整数"还是"浮点数",都是以双精度浮点类型存储的. 复制代码 代码如下: var height: number = 6; 3.string 代表字符串.跟 JavaScript 一样,可以使用一对双引号(")或一

  • 浅谈TypeScript的类型保护机制

    在编写 TS 时,它做了比我们看到的更多的事情,例如类型保护机制.让我们编写的代码更加严谨,至于怎么回事,让我们来看看吧. 由于这些机制的存在,就算你仍旧以 JS 原生的书写方式,也能帮助你提前发现代码中潜在的问题.(对于认为 TS 语句更复杂的人,也能实现 0 门槛,不改变已有的习惯也能享受静态检测的好处.) 类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域内的类型. 为了更简单的理解,我们首先声明一个联合类型用于举例: interface Bird { fly(): any; l

  • 浅谈TypeScript 索引签名的理解

    目录 1.什么是索引签名 2. 索引签名语法 3. 索引签名的注意事项 3.1不存在的属性 3.2 string 和 number 键 4.索引签名与 Record<Keys, Type>对比 我们用两个对象来描述两个码农的工资: const salary1 = { baseSalary: 100_000, yearlyBonus: 20_000 }; const salary2 = { contractSalary: 110_000 }; 然后写一个获取总工资的函数 function tot

  • 浅谈typescript中keyof与typeof操作符用法

    目录 一.keyof 简介 二.keyof 的作用 三.keyof 与对象的数值属性 四.keyof 与 typeof 操作符 一.keyof 简介 TypeScript 允许我们遍历某种类型的属性,并通过 keyof 操作符提取其属性的名称.keyof 操作符是在 TypeScript 2.1 版本引入的,该操作符可以用于获取某种类型的所有键,其返回类型是联合类型.下面我们来看个例子: interface Person {   name: string;   age: number;   lo

  • javascript学习笔记_浅谈基础语法,类型,变量

    基础语法.类型.变量 非数字值的判断方法:(因为Infinity和NaN他们不等于任何值,包括自身) 1.用x != x ,当x为NaN时才返回true; 2.用isNaN(x) ,当x为NaN或非数字值时,返回true; 3.用isFinity(x),在x不是NaN.Infinity.-Infinity时返回true; 虽然(字符串.数字.布尔值)不是对象,他们的属性是只读的,但也可以像操作对象一样来引用他们的属性和方法,原理: javascript构造一个(String.Number.Boo

  • 浅谈PHP错误类型及屏蔽方法

    程序只要在运行,就免不了会出现错误,错误很常见,比如Error,Notice,Warning等等.在PHP中,主要有以下3种错误类型. 1.注意(Notices) 这些都是比较小而且不严重的错误,比如去访问一个未被定义的变量.通常,这类的错误是不提示给用户的,但有时这些错误会影响到运行的结果. 2.警告(Warnings) 这就是稍微严重一些的错误了,比如想要包含include()一个本身不存在的文件.这样的错误信息会提示给用户,但不会导致程序终止运行. 3.致命错误(Fatal errors)

  • 浅谈c++ 字符类型总结区别wchar_t,char,WCHAR

    1.区别wchar_t,char,WCHAR ANSI:即 char,可用字符串处理函数:strcat( ),strcpy( ), strlen( )等以str打头的函数. UNICODE:wchar_t是Unicode字符的数据类型,它实际定义在里: typedef unsigned short wchar_t; 另外,在头文件中有这样的定义:typedef wchar_t WCHAR; 所以WCHAR实际就是wchar_t wchar_t 可用字符串处理函数:wcscat(),wcscpy(

  • 浅谈myBatis中的插件机制

    插件的配置与使用 在mybatis-config.xml配置文件中配置plugin结点,比如配置一个自定义的日志插件LogInterceptor和一个开源的分页插件PageInterceptor: <plugins> <plugin interceptor="com.crx.plugindemo.LogInterceptor"></plugin> <plugin interceptor="com.github.pagehelper.P

  • 浅谈Java非阻塞同步机制和CAS

    什么是非阻塞同步 非阻塞同步的意思是多个线程在竞争相同的数据时候不会发生阻塞,从而能够在更加细粒度的维度上进行协调,从而极大的减少线程调度的开销,从而提升效率.非阻塞算法不存在锁的机制也就不存在死锁的问题. 在基于锁的算法中,如果一个线程持有了锁,那么其他的线程将无法进行下去.使用锁虽然可以保证对资源的一致性访问,但是在挂起和恢复线程的执行过程中存在非常大的开销,如果锁上面存在着大量的竞争,那么有可能调度开销比实际工作开销还要高. 悲观锁和乐观锁 我们知道独占锁是一个悲观锁,悲观锁的意思就是假设

  • 浅谈Java包装类型Long的==操作引发的低级bug

    目录 背景 两个 Long  类型的  == 对 Collections.EMPTY_SET 进行 add 引发的异常 Collections 的空集合使用注意事项 启示录 背景 一个简单的列表检索功能,列表元素有一个 Long 类型的属性,遍历过程中犯了一个低级错误,导致功能流程始终错误,本文将分享两个低级错误引发的 bug. 两个 Long  类型的  == 查找某个元素 A 在列表 B 中对应的对象的时候,根据元素主键查询,主键类型为包装类型 Long ,遍历流程如下: for(MyDat

  • 浅谈数据库日期类型字段设计应该如何选择

    当设计一个产品,其中很多地方要把日期类型保存到数据库中,如果产品有兼容不同数据库产品的需求,那么,应当怎样设计呢? 当然,首先想到的是,使用数据库的 Date 或 DateTime 类型,可是看看不同数据库这些类型间的区别吧,真让人望而止步.Mysql 数据库:它们分别是 date.datetime.time.timestamp 和 year. date :“yyyy-mm-dd”格式表示的日期值 time :“hh:mm:ss”格式表示的时间值 datetime: “yyyy-mm-dd hh

随机推荐