【TypeScript】TS类型守卫(六)


【TypeScript】TS类型守卫(六)


在这里插入图片描述

    • 【TypeScript】TS类型守卫(六)
        • 一、什么是类型守卫
        • 二、in操作符
        • 三、typeof操作符
        • 四、instanceof操作符
        • 五、自定义类型谓词函数

一、什么是类型守卫

TypeScript类型守卫(Type Guards) 是一种用于在代码中确定变量类型的技术,它允许我们在运行时检查变量的类型,并根据需要执行不同的逻辑。TypeScript 类型守卫可以使用不同的语法实现,如 typeof操作符、instanceof操作符、in操作符和自定义类型谓词函数。它们可用于增强类型安全性,并提高代码的可读性和可维护性。

在上篇介绍了断言(不清楚的小伙伴点击该链接查看,【TypeScript】类型断言-类型的声明和转换(五))在使用断言时我们已经确定了变量的类型,确定该类型时一定存在(否则则会欺骗编译,运行时报错),那么为什么还要类型守卫呢?因为类型断言还是需要借助类型守卫的,类型守卫主要是用来判断未知类型是不是所需要的类型。

主要的四种类型守卫:

  • typeof操作符
  • instanceof操作符
  • in操作符
  • 自定义类型谓词函数

二、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属性,所以走了第二个判断

三、typeof操作符

类型分类场景下的身份确认
为什么用 typeof 做类型守卫呢?因为 typeof 能判断JS基本数据类型。

typeof只能识别以下类型:

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

语法:typeof a
其中a是变量(基本数据类型)

需要注意的是,对于 null 类型,使用 typeof 判断时,得到的结果是 object
typeof 识别其他的类型比如 数组,正则等都是object类型

let a =[1]
typeof a;//Objectvar 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 | B;
function 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)}
}

编译后的结果如下:
请添加图片描述

四、instanceof操作符

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

具体 instanceof 是怎么做类型守卫的呢?

语法:a instanceof b

其中 a 是参数,b 一般都是接口类型。

abstract class Teacher{name:string;courses:string;}
abstract class 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)}}

五、自定义类型谓词函数

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

语法:a is b,意思是 a是b类型a 可以是函数参数,也可以是this关键字,this关键字一般用在类中判断,b可以是接口类型,b也可以是number、string等其他合法的 TypeScript 类型。

这种写法称作类型谓词,使用类型谓词的函数称为 类型谓词函数,该函数的返回值必须的boolean类型。

使用:先定义一个变量,该变量表示是否是某种类型,比如以下定义了 isTeacher,代表了参数 cls 是 Teacher 类型,然后用这个变量来判断。

  • 函数参数形式

    函数中的参数类型为多个类型,通过 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;}return null;
    }

    编译后如下:
    请添加图片描述

  • 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}
}

以上就是【TypeScript】TS类型守卫的介绍。




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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序调用map数据 并在wxml中对数组进行截取的操作

wxs文件的位置如图 实现数组截取 只保留五张图片 <wxs module"filter" src"./slicefunc.wxs"></wxs> <view class"wrap"><view class"search-box" bindtap"toSearch"><view class"v1"…

eclipse 导入项目js报错问题

eclipse 导入项目后会出现项目中的js文件报错&#xff08;红叉&#xff09;&#xff0c;如下图所示&#xff0c;有时候报错的文件很多&#xff0c;需要集中处理。 解决办法&#xff1a; 右键项目名称》Properties》MyEclipse》JavaScript》Include Path&#xff0c;在右侧选择“…

opencv图片灰度二值化

INCLUDEPATH D:\work\opencv_3.4.2_Qt\include LIBS D:\work\opencv_3.4.2_Qt\x86\bin\libopencv_*.dll #include <iostream> #include<opencv2/opencv.hpp> //引入头文件using namespace cv; //命名空间 using namespace std;//opencv这个机器视…

jupyter切换conda虚拟环境

环境安装 conda install nb_conda 进入你想使用的虚拟环境&#xff1a; conda activate your_env_name 在你想使用的conda虚拟环境中&#xff1a; conda install -y jupyter 在虚拟环境中安装jupyter&#xff1a; conda install -y jupyter 重启jupyter 此时我们已经把该安装…

【LeetCode每日一题】——575.分糖果

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 哈希表 二【题目难度】 简单 三【题目编号】 575.分糖果 四【题目描述】 Alice 有 n 枚糖&…

下载程序到西门子PLC

更多关于西门子S7-200PLC内容请查看&#xff1a;西门子200系列PLC学习课程大纲 下载西门子200PLC程序分以下两步&#xff1a; 一.编译程序 1. 如下图1-1所示&#xff0c;使用PPI电缆将PLC和电脑连接上&#xff0c;注意笔记本使用USB转PPI电缆&#xff0c;连接保证给PLC单独供…

postman官网下载安装登录测试详细教程

目录 一、介绍 二、官网下载 三、安装 四、注册登录postman账号&#xff08;不注册也可以&#xff09; postman注册登录和不注册登录的使用区别 五、关于汉化的说明 六、使用示范 一、介绍 简单来说&#xff1a;是一款前后端都用来测试接口的工具。 展开来说&#xff1a;…

json-server的入门

由于前端开发的时候&#xff0c;需要向后端请求数据&#xff0c;有的时候后端还没有准备好&#xff0c;所以需要使用一些简单的静态数据&#xff0c;但是我们更加希望能够模拟请求以及请求回来的过程&#xff0c;这个时候就需要使用json-server Json-Server的介绍 json-server…

funbox3靶场渗透笔记

funbox3靶场渗透笔记 靶机地址 https://download.vulnhub.com/funbox/Funbox3.ova 信息收集 fscan找主机ip192.168.177.199 .\fscan64.exe -h 192.168.177.0/24___ _/ _ \ ___ ___ _ __ __ _ ___| | __/ /_\/____/ __|/ __| __/ _ |/ …

MySQL修改编码

插入中文乱码,我电脑上没有出现&#xff0c;我只是来记录一下 MySQL版本: 8.0.34Windows 查看编码 mysql中输入下面的命令 show variables like ‘character_%’; 乱码的一般是图片中划红线的部分不是utf8 character_set_database是设置数据库的默认编码的 character_set_ser…

SQL-每日一题【1484. 按日期分组销售产品】

题目 表 Activities&#xff1a; 编写解决方案找出每个日期、销售的不同产品的数量及其名称。 每个日期的销售产品名称应按词典序排列。 返回按 sell_date 排序的结果表。 结果表结果格式如下例所示。 示例 1: 解题思路 前置知识 group_concat函数的功能   将group by产生的…

模拟实现消息队列(以 RabbitMQ 为蓝本)

目录 1. 需求分析1.1 介绍一些核心概念核心概念1核心概念2 1.2 消息队列服务器&#xff08;Broker Server&#xff09;要提供的核心 API1.3 交换机类型1.3.1 类型介绍1.3.2 转发规则&#xff1a; 1.4 持久化1.5 关于网络通信1.5.1 客户端与服务器提供的对应方法1.5.2 客户端额外…

uni-app弹窗列表滚动, 弹框下面的内容也跟随滚动解决方案

滑动弹窗里的列表&#xff0c;弹框下面的内容也会跟着滑动&#xff0c;导致弹窗中的列表不能正常滚动 1.弹窗组件代码&#xff0c;需要在最外层的view中加入touchmove.stop.prevent"moveHandle"&#xff0c;且弹窗中需要滚动的列表要使用scroll-view标签包裹起来&…

JDK17下载与安装(完整图文教程含安装包)

1.下载JDK17安装包 官网下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/ 同时提供一份网盘下载地址&#xff0c;大家按需自取&#xff1a;点击下载 JDK 所有版本的安装方法都一样&#xff0c;其他版本也不用重复找教程了。 网盘直接放了 JDK 6 – …

【Linux初阶】system V - 共享内存

文章目录 前言一、共享内存初识1.共享内存的原理2.理解共享内存3.共享的内存的概念 二、共享内存函数1.shmget函数2.shmat函数3.shmdt函数4.shmctl函数 三、共享内存的查看方法及其特征四、共享内存的代码实现五、共享内存优缺点分析1.共享内存的优点2.共享内存的缺点 六、共享…

JavaWeb中Json传参的条件

JavaWeb中我们常用json进行参数传递 对应的注释为RequestBody 但是json传参是有条件的 最主要是你指定的实体类和对应的json参数能否匹配 1.属性和对应的json参数名称对应 2.对应实体类实现了Serializable接口&#xff0c;可以进行序列化和反序列化&#xff0c;这个才是实体类转…

Java课题笔记~ Request请求

1.请求消息格式 客户端发送一个HTTP请求到服务器的请求消息包括以下格式&#xff1a; 请求行&#xff08;request line&#xff09;、请求头部&#xff08;header&#xff09;、空行和请求数据四个部分组成。下图给出了请求报文的一般格式。 GET请求&#xff1a; POST请求&am…

RTT(RT-Thread)IO设备模型

目录 IO设备模型 模型框架原理 IO设备类型 创建和注册IO设备 RTT设备管理程序实现原理 访问IO设备 查找设备 初始化设备 打开设备 关闭设备 控制设备 读写设备 数据收发回调 数据接收回调 数据发送回调 设备模型实例 IO设备模型 RT-Thread 提供了一套简单的 I/O …

OptaPlanner笔记6 N皇后

N 个皇后 问题描述 将n个皇后放在n大小的棋盘上&#xff0c;没有两个皇后可以互相攻击。 最常见的 n 个皇后谜题是八个皇后谜题&#xff0c;n 8&#xff1a; 约束&#xff1a; 使用 n 列和 n 行的棋盘。在棋盘上放置n个皇后。没有两个女王可以互相攻击。女王可以攻击同一水…

机器人CPP编程基础-04输入Input

机器人CPP编程基础-03变量类型Variables Types ……AI…… C #include<iostream> // 引入iostream库&#xff0c;这个库包含了对输入/输出进行操作所需的函数和对象 using namespace std; // 使用命名空间std&#xff0c;这样我们就可以直接使用std中的名字&#xff0c…