概述

在 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类型保护的资料请关注Devmax其它相关文章!

详解TypeScript中的类型保护的更多相关文章

  1. Swift Selector

    看了喵神的Swifter100个必备的小tips总结下swift中不支持@selector关键字,将SEL重新定义为结构体了。

  2. 使用sockets:从新闻组中获取文章(三)

    >我们从服务器的这个新闻组中读取了最后的十篇文章,。也可以通过使用HEAD命令读取文章的头信息,或者使用BODY命令读取文章内容。>关于fclose()的更多信息,请参考http://www.php.net/manual/function.fclose.php结论在上文中,我们看到了怎样打开、使用然后关闭一个socket:连接到一个NNTP服务器,取回一些文章。使用POST命令发表文章也复杂不到哪儿去。下一步就是编写一个基于WEB的新闻组客户端了。这样,你有了一个基于web的搜索新闻组的程序了。

  3. Typescript中extends关键字的基本使用

    extends表示具体的泛型类型只能是object类型,某个变量如果能断言成object类型[变量as object],那么这个变量的类型符合T extends object,下面这篇文章主要给大家介绍了关于Typescript中extends关键字基本使用的相关资料,需要的朋友可以参考下

  4. JDBCTM 指南:入门5 - ResultSet

    JavaSoft目前正在准备这本书。ResultSet.next方法用于移动到ResultSet中的下一行,使下一行成为当前行。在ResultSet对象或其父辈Statement对象关闭之前,光标一直保持有效。关于ResultSet中列的信息,可通过调用方法ResultSet.getMetaData得到。返回的ResultSetMetaData对象将给出其ResultSet对象各列的编号、类型和属性。getString的返回值将为JavaString对象。TIYITSMALLITITEGERBIGNTRE

  5. TypeScript中type和interface的区别及注意事项

    type的类型别用可以用户其他的类型,比如联合类型、元祖类型、基本类型,interface不行,下面这篇文章主要给大家介绍了关于TypeScript中type和interface的区别及注意事项的相关资料,需要的朋友可以参考下

  6. 一步步带你用vite简单搭建ts+vue3全家桶

    Vue3与TS的联合是大趋势,下面这篇文章主要给大家介绍了关于用vite简单搭建ts+vue3全家桶的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

  7. vite创建一个标准vue3+ts+pinia项目

    本文主要介绍了vite创建一个标准vue3+ts+pinia项目,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  8. Vue3+TS实现语音播放组件的示例代码

    这篇文章主要介绍了如何利用Vue+TS实现一个简易的语音播放组件,文中的示例代码讲解详细,对我们学习Vue有一定的帮助,需要的可以参考一下

  9. vue3 ts编写echart是tooltip无法展示的解决

    这篇文章主要介绍了vue3 ts编写echart是tooltip无法展示的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  10. TypeScript联合类型,交叉类型和类型保护

    这篇文章主要介绍了TypeScript联合类型,交叉类型和类型保护,联合类型就是定义一些类型,定义的变量只需要满足任意一种类型即可,交叉类型就是需要满足所有类型,交叉类型使用,更多内容我们来看看下面文章详细内容吧

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部