TypeScript 类型注解(二)

news2024/11/15 11:46:34

一、TypeScript类型约束--对象

对象其实和数组类似,不是限制对象本身的类型,而是对对象属性类型进行限制

结构简化:

对对象做类型限制的好处:

大家都学习过一段时间编程了,会发现咱们经常操作的类型就是对象,尤其经常调用接口,获取对象结果,那么,通过对象类型限制就可以让编辑器很方便的提示你当前对象的属性有哪些。

这就是做完限制之后,很方便的得到提示

关于对象函数类型限制的另一个写法

- 关于对象中的可选属性如何定制

对象中的可选属性定制跟函数参数的定制一样,使用"  ?"完成

注意:

如果盗用可选属性去完成需求,必须使用 ?. 操作符,因为可选属性可能不存在,当不存在的时候就会出现致命错误,TS的优势就是会在编程阶段解决掉错误,所以,必须使用  ?.  操作符。

- 关于对象中的自定义属性如何定制

对于对象虽然可以定制可选属性,但也是约束好某个属性可有可无而已。如果说想在对象中定义一个自定义属性应该怎么办?

为了解决这个问题,可以使用对象的"任意属性"

[ propName: string ]: any

- propName就是一个占位符,换成其他的变量名字也可以。

- :string 是当前属性是一个字符串类型

- :any  any表示任意类型的意思,因为TS规定:一旦定义了任意属性,那么确定属性和可选属性的类型都必须是任意属性的类型的子集。

二、TypeScript 类型约束 - 接口

在TS中,一般会用接口(interface)对对象类型做专属约束,那么,什么是接口类型呢?

在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。

TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

- 如何通过接口(interface)约束对象类型

        - 接口如何定义

                interface 接口名称 {

                        属性1: 类型; 属性2: 类型;

                }

建议:有些编程语言建议接口前面都加上 I 关键词,比如 “IPerson”。

总结:

1. 定义接口虽然也是花括号,但是接口不是对象,所以属性之间不需要通过逗号分隔!

2. 接口大家看起来是不是和之前学习的类型别名差不多,但是他们有区别,等学完接口的基础知识点之后,在总结区别。

- 接口(interface)中的可选属性和自定义属性

- 接口(interface)还可以单独用来约束函数的形状

- 接口(interface)的多次声明

接口可以被多次声明,多次声明的属性约束会被合并。

- 接口(interface)的继承

大家跟着我思考一个问题,比如咱们之前定义了一个 IPerson 接口,他具有人类的所有属性约束,现在咱们想定义一个学生对象,那么学生对象中肯定有人类属性,并且还有一些自己独有的属性,当碰到这种情况的时候,咱们就可以利用接口的继承,让学生的接口继承人类的接口,这样就不用在学生接口中重复定义人类信息了。

- 类型别名模拟接口(interface)的继承功能

使用类型别名也是可以模拟接口的继承功能的!

- 类型别名模拟继承的功能扩展

既然能使用 & 符合链接多个约束,那么是否可以使用 | 符号链接多个约束呢?答案是肯定的。使用 | 符合链接多个约束,表示必须要完全符合某一个约束,而另一个约束可以满足或者部分满足也可以!

- 接口(interface)中的只读属性

如果你需要某个对象的属性只在第一次声明时生效,之后不允许修改,那么,可以通过关键词 readonly 实现。

补充:使用类型别名约束对象类型时,也可以定义只读属性

- 接口(interface)与类型别名约束对象的区别

大家可以发现,使用接口和类型别名都可以约束对象,那么他俩有什么区别呢?

- 命名规范

类型别名使用type关键词声明,并且名称唯一,不可重复

接口使用interface关键词声明,可以重复

类型别名中使用逗号分隔属性约束,接口中使用分号(或者不写)分隔约束。

- 使用范围

类型别名除了可以约束对象以外,还可以给他其他类型定义约束

接口只可以约束对象

- 继承

接口支持继承

类型别名虽然可以通过其他方式实现继承效果,但那不是继承

三、TypeScript类型约束--元组

在TS中,数组类型只能约束类型,而元组则是一个可以约束类型和数量的类型!

- 语法 :let 变量: [类型1,类型2] = [值1,值2]

- 使用

元组类型不仅能够约束类型和能约束个数,这在某些数据初始化时十分有用,比如你要一个存储这经纬度的数组,那么,元组就非常合适了。

- 扩展

元组也可以添加“越界元素”,但是必须是约束类型之一:

四、TypeScript类型约束--类型推论

类型推论其实咱们早就有接触,类型推论就是:TypeScript 会在没有明确的指定类型的时候推测出一个类型,这就是类型推论。

类型推论会发生在两个位置:

- 声明变量时

- 函数的返回值

五、TypeScript类型约束--字面量类型

- 什么是字面量类型

字面量类型就是将一个自定义内容当做类型使用。

- 字面量类型的特点

字面量类型要求你对某一个变量做类型约束时,值必须和字面量类型是一致的!

- 字面量类型的使用场景

字面量类型经常和联合类型一起使用,起到约束值的取值范围的作用!

六、TypeScript类型约束--枚举类型

枚举类型其实跟咱们刚才讲过的字面量类型有点相似,都是起到约束变量值范围的作用。

在详细去学枚举型之前,大家先回忆一个内容,就是《webscoket搭建网页聊天室》,当时咱们为了能够更好的处理数据,对每次的交互数据做了分类:

const MESSAGE = { ERROR: 0, GROUPMESSAGE: 1, GROUPLIST: 2 }

枚举类型就十分类似MESSAGE,不仅起到了分类说明的作用,还能起到限制取值范围的作用

- 语法格式

enum types { Mon, Tue, Wed, Thu }

 - 枚举类型的特点

咱们通过一个例子来了解一下枚举类型的特点:

通过上边的例子大家可以看出来,枚举类型不仅可以作为类型约束使用,他还可以作为值去使用。并且跟MESSAGE类似,无需关注值是什么,他的属性可以起到提示作用!

大家可以看下一枚举类型的值:console.log(types)

-枚举类型的分类

(1)数字枚举

当值为数字时,此枚举类型可以成为数字枚举。

默认在属性不赋值的情况下,属性的默认值就是数字,并且从0开始递增

当然你可以手动给数字赋值,并且有以下特点:数字会从最后一个赋值的属性开始递增

(2)字符串枚举

当值为字符串时,此枚举类型就是字符窜枚举。

相比于没有明确意义的递增值的数字枚举,字符串枚举的成员在运行和调试阶段,更具备明确的含义和可读性。

(3)异构枚举

异构枚举就是枚举类型的值有数字有字符串,不过这种枚举类型大家知道就好,异构枚举出现的情况非常的少

(4)常量枚举

常量枚举是枚举类型的一种定义方式,是在定义枚举类型的时候使用 const 关键词声明!

常量枚举跟数字枚举或者字符串枚举使用方式一样,和他们的区别是:常量枚举会在编译阶段被删除

. 想要理解什么是编译阶段删除,咱们就得理解一下枚举类型的原理!接下来,咱们学习一下枚举类型的原理。

-枚举类型的原理

枚举类型其实就是通过原生JavaScript封装好的一段程序,定制一个枚举类型,然后,在终端通过  tsc ./main.ts 解析TS文件为JS文件,查看枚举类型的源码!

编译:

分析以上解析结果不难发现,其实枚举类型就是一个值为属性、属性为值的普通对象!

(5)回忆常量枚举

常量枚举与普通枚举的区别:常量枚举会在编译阶段被删除

编译:

-枚举类型与字面量类型的一些区别

想要知道枚举类型与字面类型的一些区别,那么就要知道字面量类型存在的一些问题。

1)使用字面量类型定义一些选项时,如果值的内容需要修改,字面量类型需要修改大量内容。

对于此程序来说,如果想要将Gender 修改成 “美女/帅哥”,那么需要修改的地方有很多。

同样的程序,大家思考如果想要将Gender修改成“美女/帅哥”还会想字面量那么麻烦嘛?

(2)从编译结果来看,字面量类型不会进入到编译结果,而枚举类型会进入到编译结果

字面量类型

编译后

枚举类型

编译后

七、TypeScript类型约束--any类型

any类型就相当于是没有类型约束,因为any类型的数据可以是任意数据类型的数据!所以,在项目中,除非迫不得已,否则不推荐使用any类型去定制类型约束!

八、TypeScript类型约束--类型断言

- 什么是类型断言

类型断言就是手动指定一个值的类型!

- 语法

值 as 类型

接下来咱们通过类型断言的用途来学习一下类型断言如何使用!

- 类型断言的用途

1> 将一个联合类型断言为其中一个类型

2> 将一个父类断言为更加具体的子类

3> 将任何一个类型断言为 any

4> 将 any 断言为一个具体的类型

(1)将一个联合类型断言为其中一个类型

在TS中,因为不确定联合类型中的变量到底是哪个联合类型,所以TS只能提供联合类型中的共有属性和方法!

并且,你使用其他属性还会报错

在这种情况下,咱们就可以使用类型断言强行认定 “ani为Fish类型”,然后去访问他的legs属性!

(2)将一个父类断言为更加具体的子类

接下来,让咱们以一个例子来了解一下这种情况。

- 在你的程序中获取一下页面中的a标签,并且你想使用一下a标签的href属性

- 为什么会出现这种情况?

随便在一个有a标签的页面,获取一下a标签,然后 console.dir() 一下a标签!

console.log() 以更清晰的方式显示对象的结构 console.dir() 显示一个对象所有的属性和方法

将console结果拉到最后,大家可以看到现在的类型才是a标签正确的类型!

但是大家把鼠标放到a标签上看一下类型推论给咱们默认赋值的类型是什么:

将控制台console的对象拉到最后,打开prototype,一直找下去,你会发现类型的关系是:     HTMLAnchorElement  ->    HTMLElement  ->  Element

也就是说Element是HTMLElement的父类,HTMLElement是HTMLAnchorElement的父类。因为Element类型上是没有href属性,所以你的程序报错了。

- 解决问题

1> 在获取a标签的时候就给他指定具体类型

2> 使用类型断言将类型断言成 HTMLAnchorElement 类型

(3)将任何一个类型断言为any

理想情况下,TypeScript 的类型系统运转良好,每个值的类型都具体而精确。 当我们引用一个在此类型上不存在的属性或方法时,就会报错:

首先先要肯定这种现象,这个报错是很有必要的!

但是,有的时候咱们确实需要在某个对象上临时存储一个属性进去,比如:

现在咱们不想让这个错误出现,这时,就可以将任何一个类型转换成any了,因为any类型上访问任何属性都是可以的。

但是需要注意,将一个变量断言为 any 可以说是解决 TypeScript 中类型问题的最后一个手段。但是它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用 as any。

(4)将any断言为其他类型

在日常的开发中,我们不可避免的需要处理 any 类型的变量,它们可能是由于第三方库未能定义好自己的类型,也有可能是历史遗留的或其他人编写的烂代码,还可能是受到 TypeScript 类型系统的限制而无法精确定义类型的场景。

遇到 any 类型的变量时,我们可以选择无视它,任由它滋生更多的 any。 我们也可以选择改进它,通过类型断言及时的把 any 断言为精确的类型,亡羊补牢,使我们的代码向着高可维护性的目标发展。

- 看下面这个例子 他的返回值根本没有任何提示!

- 改进一下

完美的提示属性和方法

九、TypeScript类型约束--泛型

- 什么是泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

- 泛型的基本使用

咱们先来看一种情况,比如我定义函数,要求输入什么就输出什么:

在这个例子中有这么几个问题:

1> 因为我不能确定将来传进去什么类型的数据,所以参数的类型只能约束成any;

2> 因为参数的类型不能确定,所以返回值的类型不能确定,只能是any类型;

3> 因为返回值的类型是any,所以没有了类型提示;

接下来咱们就通过泛型解决上个案例的问题:

解释一下这个案例中的知识点:

1> 在函数名与小括号之间的<T>表示定义了一个泛型T,这里泛型的名字可以随意定义,不是非要叫T。

2> val:T 表示使用泛型T

3> (val:T):T 也表示使用泛型T

4> 调用函数时的 <string> 表示在给泛型赋值

总结:在调用函数时,给泛型赋值,那么使用泛型的位置就会以此值为准!

- 简化泛型的使用

在调用带有泛型的函数时,不是非要写<string>,可以省略;TS 会自动推断参数的类型

- 多类型的参数

泛型也是可以定义多个的,主要是应对多类型的情况!

- 泛型的类型约束

当使用泛型时,经常会用到对象类型的泛型变量,那么就会有一个问题:

当是用参数的某个属性做判断的时候,因为TS不知道此属性是否会存在,所以会报错!这是一种特别常见的场景,要解决这个问题可以使用类型约束来完成!

通过类型约束,解决泛型属性提前访问的问题:

- 类型约束配合一个关键词 keyof 使用

比如现在有这么一种需求,定义一个函数,接收一个对象和对象的某一个属性,然后函数会对此属性的值进行加工!

错误很明显,TS不知道prop是否可以用于obj!

接下来通过 keyof 关键词解决这个问题:

让U继承与T中某一项,这样就可以不仅可以解决之前的错误,还可以在使用函数时,让函数具有属性提示功能!

- 泛型接口

泛型接口就是在定义接口时,可以配合泛型,定制更具约束功能的接口;

其实在咱们平常很多时候都在使用泛型接口,

- 比如定义数组类型的第二种方式:

let arr: Array<number> = [1,2,3];

- 比如使用接口约束函数的形状

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

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

相关文章

使用miniconda构建数据科学环境

背景 数据科学中&#xff0c;不同时期项目代码往往是由不同的版本的python和第三方数据科学包构建&#xff0c;这些不同版本往往会存在兼容性问题&#xff0c;要运行这些代码&#xff0c;需要管理不同的版本的安装包。Conda是一个开源的包管理和环境管理系统&#xff0c;环境管…

Linux | 编译和使用自定义动静态库的全面解析

新竹高于旧竹枝&#xff0c;全凭老干为扶持。 - 《新竹》(郑燮) 2024.8.25 目录 1、静态库和动态库简介 静态库&#xff08;.a&#xff09;&#xff1a; 动态库&#xff08;.so&#xff09;&#xff1a; 动态库和静态库的比较&#xff1a; 2、静态库的生成和使用&#xff…

GCB | 首次揭示!气候变化对常绿和落叶植物物候差异化影响的机制

气候变化引起的植物物候改变已对全球范围内生物多样性和生态系统产生重大影响&#xff08;Nature高引文章 | 北京大学朴世龙院士等&#xff1a;全球变暖对植被物候的影响及其机制&#xff1b;Nature Ecology & Evolution | 南京大学张永光教授团队揭示延长的植被物候期受CO…

set容器的所有操作

1.基本概念 2.构造和赋值 3.大小和交换 4.插入和删除 5.查找和统计 6.set和multiset的区别 7.pair对组创建 用p.first和p.second调用前后两个属性。 8.仿函数实现降序排列 自定义数据类型也一样用仿函数&#xff1a;

【领域驱动设计 打通DDD最小闭环】领域建模

本篇BLOG为DDD流程的第二步&#xff0c;在模型的建立阶段&#xff0c;领域专家与技术人员通过领域建模来完成更为细致的模型建立讨论 领域建模的目的 领域建模主要有两个目的&#xff1a; 将知识可视化&#xff0c;准确、深刻地反映领域知识&#xff0c;并且在业务和技术人…

Python优化算法14——海鸥优化算法(SOA)

科研里面优化算法都用的多&#xff0c;尤其是各种动物园里面的智能仿生优化算法&#xff0c;但是目前都是MATLAB的代码多&#xff0c;python几乎没有什么包&#xff0c;这次把优化算法系列的代码都从底层手写开始。 需要看以前的优化算法文章可以参考&#xff1a;Python优化算…

【图文并茂】ant design pro 如何给后端发送 json web token - 请求拦截器的使用

上一节有讲过 【图文并茂】ant design pro 如何对接后端个人信息接口 还差一个东西&#xff0c;去获取个人信息的时候&#xff0c;是要发送 token 的&#xff0c;不然会报 403. 就是说在你登录之后才去获得个人信息。这样后端才能知道是谁的信息。 token 就代码了某个人。 …

工作实战-项目压测记录

1-1-1每分钟的单量 1-1-2第二版测试 2022年5月16日 17:43:11 成功 失败 其它(nginx) 真实入库单量 总单量 52 1 447 500 2022年5月16日 19:42:18 成功 失败 其它(nginx) 真实入库单量 总单量 311 689 306 1000 2-0-1. 20线程-2000单执行结果 2-1-0. 40线…

金融科技 API 接口:提升金融服务效率的关键

金融科技是应用技术手段和创新理念来提升金融服务效率的重要途径。而其中的API接口则是实现金融科技的关键。API接口的简单定义是提供计算机程序之间通信的规范和工具&#xff0c;提供一种方法和数据的交互形式&#xff0c;以便开发人员能够利用现有的软件来创建新的应用和服务…

前端网格布局display: grid;

display: grid; 块级网格 &#xff08;常用&#xff09; display: inline-grid; 行内块级网格 &#xff08;一般不用&#xff09; HTML 元素将 display 属性设置为 grid 或 inline-grid 后&#xff0c;它就变成了一个网格容器&#xff0c;这个元素的所有直系子元素将…

Mobile-Agent项目部署与学习总结(DataWhale AI夏令营)

前言 你好&#xff0c;我是GISer Liu&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;本文是DataWhale 2024 AI夏令营的最后一期——Mobile-Agent赛道&#xff0c;这是作者的学习文档&#xff0c;这里总结一下&#xff0c;和作者一起学习这个多模态大模型新项目吧&#x1f6…

开放式耳机对耳朵的伤害会减小吗?亲测好用的四款蓝牙耳机

开放式耳机对耳朵的伤害相对较小。 首先&#xff0c;开放式耳机不入耳&#xff0c;不会直接堵塞耳道&#xff0c;减少了对耳道的挤压和摩擦&#xff0c;降低了因长期佩戴入耳式耳机可能导致的耳道发炎、疼痛等问题。 其次&#xff0c;由于耳朵没有被完全封闭&#xff0c;耳部能…

【C/C++】结构体指针赋值的方法

在C语言中&#xff0c;结构体指针赋值有两种方法&#xff1a; 1.使用"->"操作符&#xff1a;通过结构体指针访问结构体成员并赋值。例如&#xff1a; struct Student {int id;char name[20]; };int main() {struct Student s1;struct Student *ptr_s1 &s1;…

设计模式学习[4]---依赖倒置原则+里氏代换原则

文章目录 前言1. 依赖倒置原则1.1 原理阐述1.2 举例 2.里氏代换原则2.1 原理阐述2.2 举例说明 总结 前言 在给发新功能模块之前&#xff0c;都先要画UML类图进行需求分析。对每一个类的作用&#xff0c;类与类之间的关系做一个详细的阐述。确定好基本的框架之后&#xff0c;才…

Lumos学习王佩丰Excel第十四讲:日期函数

一、认识时间和日期 1、回顾日期格式 日期可以由数字表示。 2、时间格式 时间由小数表示。 3、基本的时间与日期运算 二、日期函数 1、Year、Month、Day函数 2、Date函数 DATE(year,month,day&#xff09;&#xff1a;year为必需参数&#xff0c;可以包含1到4个数字。Day函…

LeetCode 热题 100 回顾

目录 一、哈希部分 1.两数之和 &#xff08;简单&#xff09; 2.字母异位词分组 &#xff08;中等&#xff09; 3.最长连续序列 &#xff08;中等&#xff09; 二、双指针部分 4.移动零 &#xff08;简单&#xff09; 5.盛最多水的容器 &#xff08;中等&#xff09; 6…

文心一言 VS 讯飞星火 VS chatgpt (332)-- 算法导论23.1 1题

一、设(u,v)是连通图G中的一条权重最小的边&#xff0c;证明&#xff1a;边(u,v)为图G的某棵最小生成树中的一条边。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 为了证明边(u,v)是图G的某棵最小生成树中的一条边&#xff0c;我们可以使用反证法结合最小生成…

09 复合查询

前面的查询都是对一张表进行查询&#xff0c;但这远远不够 基本查询回顾 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J select * from EMP where (sal>500 or job‘MANAGER’) and ename like ‘J%’; 按照部门号升序而雇员的…

免费用的写作神器:一键自动生成文章,提升内容创作效率!

传统的写作过程往往耗时耗力&#xff0c;从构思、调研到撰写、修改&#xff0c;每一步都需要创作者亲力亲为。免费写作神器的出现&#xff0c;犹如一场及时雨&#xff0c;为创作者提供了强大的支持。它利用先进的算法和自然语言处理技术&#xff0c;能够在短时间内生成高质量的…

了解Redis数据持久化(中)

3.5写时复制 Redis在使用RDB方式进行持久化时&#xff0c;会用到写时复制机制。写时复制的效果: bgsave子进程相当于复制了原始数据&#xff0c;而主线程仍然可以修改原来的数据。 对Redis来说&#xff0c;主线程fork出bgsave子进程后&#xff0c;bgsave子进程实际是复制了主线…