【TypeScript】TS类型守卫(六)

news2025/1/13 2:34:10

🐱个人主页:不叫猫先生
🙋‍♂️作者简介:前端领域新星创作者、华为云享专家、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀!
💫系列专栏:vue3从入门到精通、TypeScript从入门到实践
📝个人签名:不破不立
📢资料领取:前端进阶资料以及文中源码可以找我免费领取(文末有我wx)

在这里插入图片描述

目录

  • 类型守卫
    • 1、in- 定义属性场景下内容的确认
    • 2、typeof-类型分类场景下的身份确认
    • 3、instanceof-类型分类场景下的身份确认
    • 4、自定义类型
      • (1)函数参数形式
      • (2)this形式

类型守卫

在前几篇介绍了断言,在使用断言时我们已经确定了变量的类型,确定该类型时一定存在(否则则会欺骗编译,运行时报错),那么为什么还要类型守卫呢?因为类型断言还是需要借助类型守卫的,类型守卫主要是用来判断未知类型是不是所需要的类型
类型守卫主要包括四种方式:

  • in
  • typeof
  • instanceof
  • 自定义类型

1、in- 定义属性场景下内容的确认

先写两个接口Teacher、Student,然后将这两个接口进行联合声明,使用in来判断属性是否在传递的参数中,然后分别作输出。
缺点用 in 关键字缩小数据类型必须有一个独特的属性作为判别标准,否则不能用 in 关键字

interface Teacher{
   name:string;
   courses:string;
}
interface Student{
   name:string;
   study:string;
}
type Class = Teacher | Student;
function getInfo(val:Class){
   //此时val类型缩小为Teacher类型
   if('courses' in val){
        console.log(val.courses)
   }
   //此时val类型缩小为Student类型
   if('study' in val){
        console.log(val.study)
   }
}
getInfo({ name: 'student', study: "Philosophy" });
//打印结果为Philosophy,因为传参中含有study属性,所以走了第二个判断

2、typeof-类型分类场景下的身份确认

为什么用typeof做类型守卫呢?因为typeof能判断JS基本数据类型。typeof只能识别以下类型:

  • Boolean
  • String
  • Undefined
  • Function
  • Number
  • Bigint
  • Symbol

写法typeof a,a是变量(基本数据类型)

奇怪为什么typeof不能识别null呢?

let a= null
typeof a;//object

在这里插入图片描述
null是一个只有一个值的特殊类型,表示一个空对象引用,可以用来清空对象,它是object 类型是历史遗留下来的问题,曾提议改为null类型,被拒绝了。
typeof 识别其他的类型比如数组,正则等都是object类型

let a =[1]
typeof a;//Object
var reg = RegExp("a","i");
typeof reg//reg

typeof 怎么起到守卫的作用呢,通过typeof判断变量类型然后执行相应的逻辑,具体如下:

function class(name: string, score: string | number) {
    //识别到sore为number类型
    if (typeof score === "number") {
        return "teacher:" + name + ":" + score;
    }
     //识别到sore为string类型
    if (typeof score === "string") {
        return "student:" + name + ":" + score;
    }
}

上面案例的传参都会基本类型,当传一个对象时候,我们也可以用对象中的属性来进行判断,比如:

interface A{
   a:string;
}
interface B{
   a:number;
}
type Class = A | Bfunction getInfo(val:Class){
  //判断val的属性a的类型为number类型
   if(typeof val.a === "number"){
        console.log('B:'+ val.a)
   }
   //判断val的属性a的类型为string类型
   if(typeof val.a === "string"){
         console.log('A' + val.a)
   }
}

3、instanceof-类型分类场景下的身份确认

为什么用instanceof呢?因为typeof有局限性,引用类型比如数组,正则等无法精确识别是哪一个种型,instanceof能够识别变量(比如实例对象)是否属于这个类。instanceof不能检测原始值类型的值,但是原始值对应的对象格式实例则可以检测。具体instanceof是怎么做类型守卫的呢?

  • 写法a instanceof b,a是参数,b是一般都是接口类型。
interface Teacher{
   name:string;
   courses:string;
}
interface Student{
   name:string;
   study:string;
}
type Class = Teacher | Student;
function getInfo(val:Class){
  //判断val的类型是否是定义的接口Teacher类型
   if(val instanceof Teacher){
        console.log('teacher:'+ val.courses)
   }
   //判断val的类型是否是定义的接口Student类型
   if(val instanceof Student){
        console.log('student' + val.study)
   }
}

4、自定义类型

TS中有一个关键字is可以判断变量是否属于某种类型。

  • 写法a is b,意思是a是b类型,a是函数参数,也可以是this关键字,this关键字一般用在累中判断,b可以是接口类型,b也可以是numberstring等其他合法的TS类型。这种写法称作类型谓词,使用类型谓词的函数称为类型谓词函数,该函数的返回值必须的boolean类型。
  • 使用:先定义一个变量,该变量表示是否是某种类型,比如以下定义了isTeacher,代表了参数clsTeacher类型,然后用这个变量来判断。

(1)函数参数形式

函数中的参数类型为多个类型,通过is关键字自定义类型,将函数参数精确到某种类型,然后再执行相应的逻辑。

interface Teacher{
   name:string;
   courses:string;
}
interface Student{
   name:string;
   study:string;
}
const isTeacher = function (cls: Teacher | Student): cls is Teacher {
    return 'courses' in cls;
}
const getName = (cls: Teacher | Student) => {
    if(isTeacher(cls)) {
        return cls.courses;
    }
}

(2)this形式

下面代码中的 User 是抽象类,不能被实例化,Staff 和 Student 都继承自 User。实例方法 isStaff 用于将类型收窄为 Staff,实例方法 isStudent 用于将类型收窄为 Student

abstract class User {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    isStudent(): this is Student {
        return this instanceof Student;
    }
    isStaff(): this is Staff {
        return this instanceof Staff; 
    }
}

class Student extends User{
    study: string;
    constructor(name: string, study: string) {
        super(name)
        this.study = study
    }
}

class Staff extends User {
    workingYears: number;
    constructor(name: string, workingYears: number) {
        super(name)
        this.workingYears = workingYears
    }
}

function judgeClassType(obj: User) {
    if (obj.isStaff()) {
        // obj的类型被缩小为 Staff
    } else if (obj.isStudent()){
        // obj 的类型被缩小为 Student
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/145760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

独立开发变现周刊(第86期):月收入4000美元的日程规划器

分享独立开发、产品变现相关内容,每周五发布。目录1、NotionReads: 在Notion中管理你的阅读书籍2、Zaap.ai: 面向创作者的一站式工具3、microfeed: 开源的可自我托管的轻量级内容管理系统(CMS)4、Reactive Resume:一个免费的开源简历生成器5、一个月收入…

2019年1月政企终端安全态势分析报告

声明 本文是学习2019年1月政企终端安全态势分析报告. 下载地址 http://github5.com/view/55037而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 漏洞利用病毒攻击政企分析 奇安信终端安全实验室监测数据显示,2019年4月,有6.7%的…

JavaScript中的元编程

紧接上回,伴随着Reflect,Proxy降世,为js带来了更便捷的元编程! 什么是元编程?这词第一次听,有点懵,好像有点高级,这不得学一下装…进自己的知识库 概念 元编程是一种编程技术&…

【数据结构与算法】Collection接口迭代器

Java合集框架 数据结构是以某种形式将数据组织在一起的合集(collection)。数据结构不仅存储数据,还支持访问和处理数据的操作 在面向对象的思想里,一种数据结构也被认为是一个容器(container)或者容器对象…

【MySQL】MySQL表的七大约束

序号系列文章1【MySQL】MySQL介绍及安装2【MySQL】MySQL基本操作详解3【MySQL】MySQL基本数据类型4【MySQL】MySQL表的七大约束文章目录MySQL表的约束1,默认约束2,非空约束3,唯一约束4,主键约束5,自增约束6&#xff0c…

详细分析单调栈,及正确性证明

什么是单调栈 对于一个数组,需要对每个位置生成,左右两边离它最近的,比它小(或比它大)的位置在哪 例如: 如果对每个位置都遍历下左右两边,找到第一个比它小的位置,就是O(N ^ 2)的…

IPv6 时代如何防御 DDoS 攻击?

在互联网世界,每台联网的设备都被分配了一个用于标识和位置定义的 IP 地址。20 世纪 90 年代以来互联网的快速发展,联网设备所需的地址远远多于可用 IPv4 地址的数量,导致了 IPv4 地址耗尽。因此,协议 IPv6 的开发和部署已经刻不容…

从第三方平台导出大数据量本地Excel怎么解决性能问题?

对于日常需要做分析的我们来说,周期性需要从第三方系统导出数据,日积月累数据量越来愈大,由开始的几百条数据慢慢增至十几万甚至百万级的数据量,在本地Excel直接做分析汇总老是卡顿等半天,效率日益低下,每天…

连续四年发布科技趋势预测,他们在探索中国科技的“主干道”

,*本文配图由百度飞桨文心一格提供AI绘画技术支持。古希腊流传着一句谚语:智慧不仅是能够明察眼前,更要能够预测未来。身处科技界,一到年底年初我们就会看到各种各样的趋势预测。这些预测五花八门,神奇多变。但大多数科…

JAVA中使用最广泛的本地缓存?Ehcache的自信从何而来3 —— 本地缓存变身分布式集群缓存,打破本地缓存天花板

大家好,又见面了。 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面。如果感兴趣,欢迎关注以获取后续更新。 上一篇文章中,我们知晓了如何在项目中通过不同的…

【Python】Numpy处理多项式类Polynomial

文章目录构造函数求导和积分求根和反演采样与拟合其他方法构造函数 Numpy中提供了多项式模块,里面封装了一些用以快速解决多项式问题的类和函数,其中最重要类的自然是Polynomial,其构造函数为 class numpy.polynomial.polynomial.Polynomia…

list容器的底层结构(详述insert()与erase())

目录 一、带头结点的双向循环链表(list) 二、贯穿list容器的insert与erase接口​编辑 一、带头结点的双向循环链表(list) 二、贯穿list容器的insert与erase接口 通过在指定位置的元素之前插入新元素来扩展容器。 这有效地增加了…

520页(17万字)集团大数据平台整体解决方案-v1.0

【版权声明】本资料来源网络,知识分享,仅供个人学习,请勿商用。【侵删致歉】如有侵权请联系小编,将在收到信息后第一时间删除!完整资料领取见文末,部分资料内容: 1.1.1 系统总体逻辑结构 4-14系…

Golang 面试题总结

一.基础部分 go语言的值类型和引用类型? 值类型:int、float、bool、string和数组这些类型都属于值类型。 值类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中。当使用 将一个变量的值赋给另一个变量时,如 j i ,实…

九、k8s 安全认证

文章目录1 访问控制概述2 认证管理3 授权管理4 准入控制1 访问控制概述 Kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。 客户端 在Kubernetes集群中&#…

MySQL调优-深入理解MVCC机制

目录 MySQL调优-深入理解MVCC机制 MVCC多版本并发控制机制 undo日志版本链与read view机制详解 根据图2和图3对应画出下图的undo日志版本链: 版本链比对规则: 注意: 举例1:分析一下下图select1的read_view以及各个select语句…

Cadence PCB仿真使用Allegro PCB SI导入其他板卡的层叠结构的方法图文教程

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 目录 1,概述2,导入方法3,总结1,概述 本文详细介绍使用Allegro PCB SI PCB仿真软件导入其他电路板层叠结构的方法。 2,导入方法 第1步:打开待仿真的PCB文件,并确认软件为Allegro PCB SI 如果,打开软件不是Allegro PC…

STL-vector的接口使用及模拟实现

文章目录vector类的介绍vector类的常用接口介绍 构造相关 无参构造迭代器区间构造拷贝构造 容量相关的接口 sizereserveresizecapacityempty 数据访问及遍历相关的接口 operator[]begin endrbegin rend 修改数据相关的接口 push_backpop_backinserterase vector类的模拟实现…

excel统计函数:应用广泛的动态统计之王OFFSET 下篇

【前言】在上篇文章中,我们了解了OFFSET函数的运算原理和各个参数的作用,并且我们也通过一些OFFSET的案例,了解了它的用途。那么本篇我们继续来看看,OFFSET函数在实际工作中所能起到的强大效果吧。一、高阶应用的思路(…

vector使用指南

目录 引言 空间配置器 vector 与 string的一些差异 vector容器与string容器的一些差异 接口介绍——reserve resize接口 shrink_to_fit 接口 operator[ ] 和 at 接口 assign接口 增删查改接口 swap接口 例题讲解 引言 vector实质上就是数据结构的顺序表&#xff0…