Typescript高级: 深入理解断言

概述

  • 关于断言,就是TS 类型断言,即把两种能有重叠关系的数据类型进行相互转换的一种 TS 语法
  • 把其中的一种数据类型转换成另外一种数据类型
  • 类型断言和类型转换产生的效果一样,但语法格式不同
  • TS 类型断言语法格式:A 数据类型的变量 as B 数据类型
  • 注意:A 数据类型和 B 数据类型必须具有重叠关系

关于重叠关系的几种场景


1 ) 如果 A,B 是类并且有继承关系

  • 这里,存在 extends 关系,无论 A,B 谁是父类或子类
  • A 的对象变量可以断言成 B 类型,B 的对象变量可以断言成A类型
  • 但注意一般在绝大多数场景下都是把父类的对象变量断言成子类
class People {public myusername!: string;public myage!: number;public address!: stringpublic phone?: stringconstructor() {}eat() {}step() {console.log("People=>step");}
}class Stu extends People {public username!: stringpublic age!: number;public address!: stringconstructor(username: string, age: number, address: string, public phone: string) {super();this.address = address;}study() {}
}function test1() {const stu = new Stu("wangwu", 23, "北京", "123")const result = stu as People; // 正确 这是断言// const result = <People>stu; // 正确 这是类型转化result.step() // 可正常调用 验证了可以调用父类的方法
}function test2() {const people = new People()// const result = people as Stu; // 类型断言 正确const result = <Stu>people;// 类型转换 正确// result.step(); // 正常输出 可以正常调用父类自己的方法result.study(); // 错误,不可以调用 Stu 的方法
}// test1()
// test2()
  • 两个类之间断言的规则, 两个类中任意一个的属性和方法是另一个类的属性和方法完全相同或子集
  • 则这两个类可以相互断言, 否则这两个类就不能相互断言
  • 注意,上述,即使可以相互断言,但是也无法调用两者不相同的方法

2 ) 如果 A,B 是类,但没有继承关系

  • 两个类中的任意一个类的所有的 public 实例属性【不包括静态属性】, 加上所有的 public 实例方法
  • 和另一个类的所有 public 实例属性加上所有的public 实例方法完全相同或是另外一个类的子集
  • 则这两个类可以相互断言, 否则这两个类就不能相互断言
class People {constructor(public username: string, public age: number, public address: string) {}study() { console.log('People study')} // 这个可以注释掉看下
}class Stu {public  username!: stringpublic age!: number;public address!: stringpublic phone!:string;constructor(username: string, age: number, address: string) {this.address = address;}public study() { console.log('Stu study') }
}function test1() {const people = new People("wangwu", 23, "beijing")// const result = people as Stu; // 可以正确断言const result = <Stu>people; // 可以正确转换result.study(); // 正确调用,输出 People study
}function test2() {const stu = new Stu("wangwu", 23, "北京")stu.study() // 可以正常调用const result = stu as People; // 正确断言// const result = <People>stu; // 正确转换result.study() // 正确调用,与上面输出一致,注意,这里并不是调用 People 中的study
}// test1()
// test2()

3 ) 如果 A 是类,B 是接口,并且 A 类实现了 B 接口【implements】

  • 符合以上条件,则 A 的对象变量可以断言成 B 接口类型
  • 同样 B 接口类型的对象变量也可以断言成A类型
interface People {username: string, age: number, address: string, phone: string
}class Stu implements People {public username!: stringpublic age!: numberpublic address!: stringpublic phone!: stringpublic kk() {}get value() {return this.username}set value(newVal) {this.username = newVal}constructor(username: string, age: number, address: string) {this.address = address;}
}function test1() {const people: People = { username: "wangwu", age: 23, address: "11", phone: "111" }const result = people as Stu; // 断言 正确const result2 = <Stu>people;// 类型转换 正确
}function test2() {const stu = new Stu("wangwu", 23, "北京")const result = stu as People; // 断言 正确const result2 = <People>stu // 类型转化 正确
}test1()
test2()

4 )如果 A 是类,B 是接口,并且 A 类没有实现 B 接口

  • 符合上述场景,则断言关系和场景2的规则完全相同
interface People {username: string, age: number, address: string, phone: string
}class Stu {public username!: stringpublic age!: number;public address!: stringpublic phone!: stringpublic kk() {}get value() {return this.username}set value(newVal) {this.username = newVal}constructor(username: string, age: number, address: string) {this.address = address;}
}function test1() {const people: People = { username: "wangwu", age: 23, address: "11", phone: "111" }const result = people as Stu; // 断言正确
}function test2() {const stu = new Stu("wangwu", 23, "北京")stu as People; // 断言正确
}test1()
test2()

5 )如果 A 是类,B 是 type 定义的数据类型

  • B 就是引用数据类型, 例如 Array 对象 (不能是基本数据类型,例如 string,number, boolean)
  • 并且有 A 类实现了 B type 定义的数据类型 implements
  • 则 A 的对象变量可以断言成 B type 定义的对象数据类型
  • 同样 B type 定义的对象数据类型的对象变量也可以断言成 A 类型
type People = {username: string, age: number, address: string, phone: string
}class Stu implements People {public username!: stringpublic age!: number;public address!: string// 类型 "Stu" 中缺少属性 "address",但类型 "typestu2" 中需要该属性。tpublic phone!: stringget value() {return this.username}set value(newVal) {this.username = newVal}constructor(username: string, age: number, address: string) {this.address = address;}
}function test1() {const people: People = { username: "wangwu", age: 23, address: "11", phone: "111" }people as Stu; // 断言正确
}function test2() {const stu = new Stu("wangwu", 23, "北京")stu as People; // 断言正确
}test1()
test2()

6 ) 如果 A 是类,B 是 type 定义的数据类型,并且 A 类没有实现 B type定义的数据类型

  • 如果符合上述场景,则断言关系和第2种场景的规则完全相同
type People = {username: string, age: number, address: string, phone: string
}class Stu {public username!: stringpublic age!: numberpublic address!: stringget value() {return this.username}set value(newVal) {this.username = newVal}constructor(username: string, age: number, address: string) {this.address = address;}
}function test1() {const people: People = { username: "wangwu", age: 23, address: "11", phone: "111" }// const result = people as Stu; // 报错:类型 "People" 到类型 "Stu" 的转换可能是错误的,因为两种类型不能充分重叠。如果这是有意的,请先将表达式转换为 "unknown"。类型 "People" 中缺少属性 "value",但类型 "Stu" 中需要该属性
}function test2() {const stu = new Stu("wangwu", 23, "北京")// stu as People; // 报错:类型 "Stu" 到类型 "People" 的转换可能是错误的,因为两种类型不能充分重叠。如果这是有意的,请先将表达式转换为 "unknown"。 类型 "Stu" 中缺少属性 "phone",但类型 "People" 中需要该属性。
}test1()
test2()

7 ) 如果 A 是一个函数上参数变量的联合类型,例如 string | number

  • 如果符合上述条件,那么在函数内部可以断言成 string 或number 类型
function selfMutiply(one: string | number) {// one as number +3;
}

8 )多个类组成的联合类型的断言

  • 例如:const vechile: Car | Bus | Trunck
  • vechile 可以断言成其中任意一种数据类型
  • 例如 vechile as Car, vechile as Bus , vechile as Trunck
class Car {public name: string
}class Bus {public color: string
}class Trunck {public weight: number
}let vechile: Car | Bus | Trunck // 注意,这里是 let, 使用 const 必须初始化
const x = vechile as Car // 断言正确
const y = vechile as Bus // 断言正确
const z = vechile as Trunck // 断言正确

9 )any 或 unknown 类型

  • 任何数据类型都可以转换成 any 或 unknown 类型
  • any 或 unknown 类型也可以转换成任何其他数据类型
function testAny(one: string | number, two: string | number) {return one as any + two as any
}function testUnknow(one: string | number, two: string | number) {one as unknowntwo as unknownconsole.log(one)console.log(two)
}console.log(testAny(3, 5)) // 8
console.log(testAny("3", 5)) // 35testUnknow(1, "5") // 1 5

10 ) Symbol 中的断言

  • Symbol 可以直接作为对象的索引
  • Symbol 类型也可以断言为 any 进行访问
  • Symbol 类型不可以断言为 unknown 来访问
const symid = Symbol("objid") // 定义一个 Symbol
const obj = { [symid]: 101, username: "wangwu", age: 23 } // 
const username = obj["username"]
const objid = obj[symid] // 这个可以访问
console.log(objid) // 101const objid1 = obj[symid as any] // 这个也可以
console.log(objid1) // 101// const objid2 = obj[symid as unknown] // 这个是错误的,直接会报错 类型“unknown”不能作为索引类型使用

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

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

相关文章

在 Kubernetes 上运行 Apache Spark 进行大规模数据处理的实践

在刚刚结束的 Kubernetes Community Day 上海站&#xff0c;亚马逊云科技在云原生分论坛分享的“在 Kunernets 上运行 Apache Spark 进行大规模数据处理实践”引起了现场参与者的关注。开发者告诉我们&#xff0c;为了充分利用 Kubernetes 的高可用设计、弹性&#xff0c;在越来…

AIGC (AI-Generated Content) 技术深度探索:现状、挑战与未来愿景

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f916; AIGC技术&#xff1a;塑造未来的创意与内容革命 &#x1f31f;引言 &#x1f680;AIGC技术发展现状 &#x1f4c8;核心技术驱动 &#x1f4a1;应用领域拓展 &#x1f310; 面临的挑战 ❌真实性与伦理考量 &am…

SAP-CentralFinance - 会计核算中的组织要素 - 学习心得1

1. 定义SAP组织架构和理解各组织架构含义 组织结构遍布SAP 系统的所有重要功能范围。FI 中最重要的组织要素是公司代码。它是“财务会计”中的最小组织单位,可以为其编制自主式完整科目集供外部报告使用。其他重要的组织要素是利润中心业务范围和段。您可以为各个利润中…

大模型微调之 在亚马逊AWS上实战LlaMA案例(十)

大模型微调之 在亚马逊AWS上实战LlaMA案例&#xff08;十&#xff09; 训练数据集格式 SageMaker JumpStart 目前支持域适应格式和指令调整格式的数据集。在本节中&#xff0c;我们指定两种格式的示例数据集。有关更多详细信息&#xff0c;请参阅附录中的数据集格式化部分。 …

Vue进阶(贰零捌)浏览器地址栏URL防篡改攻略

文章目录 一、前言二、动态路由三、Params 参数四、在 URL 中使用加密参数五、参数转码六、综述七、拓展阅读 一、前言 在应用 vue.js 开发前端项目时&#xff0c;浏览器中url 地址栏参数的处理是一个很基础但却很重要的问题。在很多情况下&#xff0c;我们需要从 url 中获取参…

采购管理软件:采购自动化提高效率的5种方式

在采购领域&#xff0c;手动数据输入和耗时的文书工作的时代已经落后了。采购自动化正在改变游戏规则&#xff0c;使企业能够简化流程、降低成本并提高效率。 以下是采购自动化帮助企业提高效率的5种方法。 采购管理软件,采购自动化管理,8Manage SRM,高亚科技 减少手动流程和…

安卓手机APP开发__屏幕兼容性概述

安卓手机APP开发__屏幕兼容性概述 目录 概述 屏幕大小 灵活的布局 备选的布局 可改写的图像 像素的深度 深度依赖 备选的位图 向量图形 概述 安卓运行各种各样的设备&#xff0c;它们有不同的屏幕大小和屏幕的像素深度。 系统执行基本的缩放和变形来适配在不同的屏幕…

iview(viewUI) span-method 表格实现将指定列的值相同的行合并单元格

效果图是上面这样的&#xff0c;将第一列的名字一样的合并在一起&#xff1b; <template><div class"table-wrap"><Table stripe :columns"columns" :data"data" :span-method"handleSpan"></Table></div&…

HDFS- DataNode磁盘扩缩容

HDFS- DataNode磁盘扩缩容 背景: 缩减/增加节点磁盘 方案介绍: 采用hdfs dfsadmin -reconfig 动态刷新配置实现,不停服扩缩容。 注意事项: 请在进行缩容之前,务必了解实际的数据量,并确保磁盘有足够的空间来容纳这些数据。还需要考虑未来的使用需求,要预留一定数量的空间…

如何成为一个优秀的程序员

1 衡量一个程序员是否优秀&#xff0c;不是看程序员懂多少编程语言和编程技能&#xff0c;也不是看程序员做过多少项目&#xff0c;写过多少行代码&#xff0c;发表多少篇技术文章&#xff0c;甚至也不是看程序员的工作年限。 衡量程序员&#xff0c;第一看薪资&#xff0c;第…

java+vue3+iclientol实现警务地理信息系统实践

警务地理信息系统&#xff08;Police Geographic Information System, PGIS&#xff09;是一种专为警务工作设计的地理信息系统&#xff0c;它结合了地理信息技术、数据库技术、网络技术和现代警务理念&#xff0c;旨在提升公安机关的空间数据分析、决策支持、指挥调度、案件管…

SpringMVC的WebMvcConfigurer及返回

由于很久很久没有做过纯springmvc的代码了&#xff0c;好多东西都遗忘&#xff0c;最近接手了一个古早项目springmvc的。记录一下&#xff1a; 1、WebMvcConfigurer 是 Spring Framework 中的一个接口&#xff0c;它提供了一种扩展 Spring MVC 配置的方式。通过实现 WebMvcConf…

【QVariant类型剖析】

QVariant类型剖析 &#x1f31f; 官方文档中给出的定义&#x1f31f; 特性&#x1f338;QVariant实战应用&#x1f338;项目成果展示 &#x1f31f; 官方文档中给出的定义 &#x1f4d8;Because C forbids unions from including types that have non-default constructors or…

基于springboot+vue+Mysql的外卖点餐系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

【.NET Core】你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟

你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟 文章目录 你认识Attribute之CallerMemberName、CallerFilePath、CallerLineNumber三兄弟一、概述二、CallerMemberNameAttribute类三、CallerFilePathAttribute 类四、CallerLineNumberAttribute 类…

Android 简单的下拉选择框实现

要实现这种效果,目前知道的方法有以下两种,Spinner 和 ListPopupWindow,当然肯定还有很多别的方法,这里我们先尝试使用ListPopupWindow来实现这个效果; 以下是一个简单的demo: public class MainActivity extends AppCompatActivity {private List<String> dataList;pr…

三方库的调用方法

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言三方库的调用方法1. **下载并安装Boost库(三方库)**2. **配置开发环境**3. **包含Boost(三方库)头文件**4. **编写代码**5. **链接Boost库(三…

QueryPerformanceCounter实现高精度uS(微妙)延时

参考连接 C# 利用Kernel32的QueryPerformanceCounter封装的 高精度定时器Timer_kernel32.dll queryperformancecounter-CSDN博客https://blog.csdn.net/wuyuander/article/details/111831973 特此记录 anlog 2024年5月11日

ubuntu安装oceanbase调通本地navicat链接

分为两部分 一安装oceanbase服务 准备工作 mkdir -p /data/1 /data/log1 chown -R admin.admin /data/1 /data/log1/偷偷说&#xff1a;其实这步我忘记执行&#xff0c;也没影响我安装 oceanbase程序是很占内存的在安装时我们要先下载好安装包&#xff1a; 然后放在能记住的…

【C语言】/*操作符(上)*/

目录 一、算数操作符&#xff1a;、-、*、/、% 1.1 和 - 1.2 * 1.3 / 1.4 % 二、赋值操作符&#xff1a; 和符合赋值 2.1 连续赋值 2.2 复合赋值(自操作) 三、单目操作符&#xff1a;、--、(正号)、-(负号) 3.1 和 -- 3.1.1 前置 3.1.2 后置 3.1.3 前置-- …