你的 TypeScript 还只是用来声明 string、number……的吗?

news2024/12/26 14:46:40

深入TS类型

联合类型

使用|操作符将变量可能出现的数值类型连接起来,就是联合类型

function css(ele: Element, attr: string, value: string | number) {// value参数的类型只能是string或者number
	// ......
} 

交叉类型

使用&操作符将多种类型合并在一起,形成一种新的类型

type t1 = {name: string,age: number
}
type t2 = {sex: string
}

type t3 = t1 & t2

function sayHi(person: t3) {console.log(`${person.name}今年${person.age}岁,性别:${person.sex}`)
}
let king = {name: 'king',age: 12,sex: 'man'
}
let ali = {name: 'king',sex: 'woman'
}
sayHi(king)
sayHi(ali) // 报错 

这里t1和t2两个类型通过交叉合并为一种类型,要求必须含有三个属性并且符合数据类型限定,上面的代码中最后一行会抛出错误,因为变量ali不满足t3类型的要求

这里需要说一下interface和type,都可以描述一个对象或者函数,interface用来定义接口,type定义类型,二者并不是互相独立的。

这里说一下二者的区别:

  • type可以直接通过运算获得新类型,而interface需要使用extends操作符来生成新的接口。
  • type 语句中还可以使用 typeof 获取实例的类型进行赋值
  • interface 能够声明合并,多个同名interface声明的类型会被合并到同一接口

从图中可以看到interface也可以来继承type,并且实现相同功能

字面量类型

TS类型限定除了基本数据类型限定之外还可以进行具体值的限定

type t1 = {name: string,sex: 'man' | 'woman'
}

let person: t1 = {name: '张三',sex: 'middle' // 报错
} 

如上,使用字符串限定之后sex的值之能是man或者woman。除了字符串以外,其他的基本数据类型也都可以限制

类型别名

可以使用type操作符对任意类型获取组合类型起别名

类型推导

每次都显式标注类型太麻烦,TS提供了一种方便的特性——类型推导。根据上下文自动推导出对应的类型标注,过程发生在:

  • 初始化变量
  • 设置函数默认参数
  • 返回函数值

类型断言

有的时候我们需要一个更精确的标注,比如使用document.querySelector方法获得的结果,TS会根据参数判断返回值的类型。如果是一个图片,他有src属性,而如果是一个div,他就没有src属性。

但是TS并不会知道我们使用了类选择器之后的结果,我们需要提前告知

let ele = <HTMLImageElement>document.querySelector('.box')
// 或者
let ele2 = document.querySelector('.box') as HTMLImageElement 

断言也可以联合类型参数带来的问题吗,如果参数是联合类型,比如string | string[],参数有可能是数组也有可能是字符串,那么无法判断参数是否具有某一方法,这时候就可以使用类型断言来调用方法

类型保护

上面说的联合类型参数带来的问题也可已通过类型保护来解决

function fun(str: string | string[]) {if (typeof str === 'string') {str.split('')} else {// 当其他类型都在if中罗列之后,剩余的一种在else中生效str.push()}
} 

intanceof也可以触发类型保护

类型操作符

keyof

可以获取类型的键名组成的联合类型,主要用途是key的合法化

type Person = {name: string;age: number;
}
type PersonKey = keyof Person;
// PersonKey得到的类型为 'name' | 'age'

function getValue(p: Person, k: keyof Person) {return p[k];
} 

typeof

获取一个对象/实例的类型,只能用在具体的对象上

in

只能用在类型的定义中,可以对枚举类型进行遍历

// 这个类型可以将任何类型的键值转化成number类型
type TypeToNumber<T> = {[key in keyof T]: number
} 

泛型

泛型在之前的入门中也有所涉及,但那只是皮毛中的皮毛,现在我们来深入一下泛型,基本的泛型定义不再赘述,可以去看一下TypeScript的入门笔记

泛型推导

如同前面所说的类型推导一样,泛型也有推导,

type Dog<T> = {name: string,type: T
}

function doSth<T>(dog: Dog<T>) {return dog.type
}

let dog = {name: 'lucky',type: 'pug'
}
// 如果没有泛型推导,就需要写这么多
// let dog: Dog<string> = {
// name: 'lucky',
// type: 'pug'
// }

doSth(dog)	// 调用函数时根据type的类型自动推导出了T 

类型约束

有时候,我们需要限定类型,这时候使用extends关键字

function sum<T extends number>(value: T[]) {let count = 0value.forEach(v => count += v)return count
} 

使用extends限定参数类型为数字数组,如果调用时参数出现了其他类型就会报错

还可以限制多个参数,如

function pick<T, U extends keyof T>(obj: T, proto: U) {console.log(obj[proto]);
};

let person = {name: '张三',age: 14
}

pick(person, 'name') 

第二个参数必须是第一个参数中keys的子集,否则报错

泛型推断

使用infer关键字来进行泛型推断

type Per<T> = T extends { t: infer P } ? P : string

type p = Per<number> // string
type p1 = Per<{ t: boolean }> // boolean
type p2 = Per<{ t: number }>// number 

定义Per的过程也叫泛型条件,通过三目运算符控制最终分配的类型。根据传进来的泛型类型T有无t属性来确定返回的类型,并将t的属性返回

常用泛型工具

Partial

Partial的作用是将传入的属性变成可选项,原理就是使用keyof拿到所有属性名,然后再使用in遍历,使用?将属性设置为可选属性,其实现源码如下

type Partial<T> = {[P in keyof T]?: T[p]
}

type person = {name: string,age: number
}

// 使用Partial处理后没有全部属性不再报错
let a: Partial<person> = {name: '1q23'
} 

Required

Required将所有的参数变为必选项;其原理是使用keyof拿到所有属性名,然后再使用in遍历,可以理解为使用-?抵消掉?

type Required<T> = {[P in keyof T]-?: T[P]
}

type person = {name: string,age: number
}

let b: Required<person> = {name: 'king',
} 

Record

Record作用是用于构造键为K类型值为T类型的对象,源码也比较简单,将K中的每个属性设置为T类型

type Record<K extends keyof any,T> = {[key in K]: T
}
// keyof any对应的类型为number | string | symbol,就是可以做索引的类型集合

type person = {name: string,age: number
}

let c: Record<number, string> = {1: 1,'str': 123
} 

这里会抛出异常,因为使用Record工具将所有的number类型为索引的属性值类型设置为string,数字索引的属性不是string就会报错

Pick

Pick的作用是将 T 类型中的 K 键列表提取出来,生成新的子键值对类型

type Pick<T, K extends keyof T> = {[P in K]: T[P]
}

type person = {name: string,age: number
}

let d: Pick<person, 'name'> = {name: 'king',age: 12 // 不能将类型“{ name: string; age: number; }”分配给类型“Pick<person, "name">”。对象文字可以只指定已知属性,并且“age”不在类型“Pick<person, "name">”中
} 

因为使用Pick工具从person类型中只选择了name属性,所以添加age属性之后会报错

Exclude

Exclude的作用是去除 T 类型和 U 类型的交集,返回剩余的部分

type Exclude<T, U> = T extends U ? never : T

type person = {name: string,age: number
}

type el = Exclude<person | string, number | 'a' | person> // string
let e: el = 'str' 

Omit

Omit用于键值对对象的 Exclude,它会去除类型 T 中包含 K 的键值对

type Omit = Pick<T, Exclude<keyof T, K>>

type person = {name: string,age: number
}

type oi = Omit<person, 'age'>
let f: oi = {name: 'king'
} 

ReturnType

ReturnType获取 T 类型(函数)对应的返回值类型,通过使用 infer 推断返回值类型,然后返回此类型

type ReturnType<T extends (...args: any) => any>= T extends (...args: any) => infer R ? R : any;

type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void 

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

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

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

相关文章

JavaSE · 常量介绍 · 变量类型转换 · 理解数值提升 · int 和 Stirng 之间的相互转换

书接上回 Java 变量介绍 我们继续学习以下内容. 四、常量字面值常量final 关键字修饰的常量五、理解类型转换int 和 long/double 相互赋值int 和 boolean 相互赋值int 字面值常量给 byte 赋值强制类型转换类型转换小结六、理解数值提升int 和 long 混合运算byte 和 byte 的运算…

你还在用CSS旧时代布局的王者:浮动float 吗?

写在前面 随着flex、grid等布局的兼容性越来越好&#xff0c;float几乎已经在大众的视野消失了&#xff0c;曾经默认的小妖精终究成为了时代的眼泪。 作为前端开发者&#xff0c;你经历过float的时代吗&#xff1f;还在用float吗&#xff1f; 一、什么是浮动&#xff1f; 首…

ccc-台大林轩田机器学习基石-hw0

文章目录1 Probability and Statistics2 Linear Algebra3.Calculus一览图hw0题目链接1 Probability and Statistics 不妨假设C(n,K)C(n,K)&#xff0c;0≤K≤NC(n, K)C(n, K) &#xff0c;0 \le K\le NC(n,K)C(n,K)&#xff0c;0≤K≤N成立&#xff0c;只需证明C(n1,K)(n1)!K!(…

list类的使用和模拟实现

目录 一、list类的介绍 二、list的使用 1.构造、拷贝构造函数和迭代器 2.数据的增删查改 三、list的部分接口实现 1.节点定义 2.list类的组织 四、list的迭代器 1.迭代器的设计思路 2.const迭代器 3.->操作符的重载 4.反向迭代器 一、list类的介绍 list就是C库…

Elasticsearch基本概念和索引原理

一、Elasticsearch是什么&#xff1f; Elasticsearch是一个基于文档的NoSQL数据库&#xff0c;是一个分布式、RESTful风格的搜索和数据分析引擎&#xff0c;同时也是Elastic Stack的核心&#xff0c;集中存储数据。Elasticsearch、Logstash、Kibana经常被用作日志分析系统&…

[CCS 2022] 皇帝没有衣服:用于网络安全的AI/ML

AI/ML for Network Security: The Emperor has no ClothesCCS 22: Proceedings of the 2022 ACM SIGSAC Conference on Computer and Communications Securityhttps://dl.acm.org/doi/abs/10.1145/3548606.3560609摘要最近的一些研究工作提出了基于机器学习&#xff08;ML&…

工业废水的种类及其处理工艺有哪些?特定目标污染物的深度去除

随着工业的迅速发展&#xff0c;工业废水的种类和数量随之增加&#xff0c;对水体的污染也日趋严重&#xff0c;威胁人类的健康和正常生活。所以工业废水的处理对于环保至关重要。 保护生态环境、更好地做好工业废水的处理&#xff0c;了解工业废水及其种类与处理非常必要。 工…

MySQL 删除数据库

使用普通用户登陆 MySQL 服务器&#xff0c;你可能需要特定的权限来创建或者删除 MySQL 数据库&#xff0c;所以我们这边使用 root 用户登录&#xff0c;root 用户拥有最高权限。 当数据库不再使用时应该将其删除&#xff0c;以确保数据库存储空间中存放的是有效数据。删除数据…

【Hello Linux】 Linux基础命令

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍Linux的基础命令 Linux基础命令ls指令lsls -als -dls -ils -sls -lls -nls -Fls -rls -tls -Rls -1总结思维导图pwd指令whoami指令…

Python 条件语句

Python条件语句是通过一条或多条语句的执行结果&#xff08;True或者False&#xff09;来决定执行的代码块。可以通过下图来简单了解条件语句的执行过程:Python程序语言指定任何非0和非空&#xff08;null&#xff09;值为true&#xff0c;0 或者 null为false。Python 编程中 i…

【正点原子FPGA连载】第八章UART串口中断实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第八章UART串口中…

【SSD 代码精读】之 数据增强(Data Augmentation)

SSD 数据增强前言1、Compose2、SSDCropping3、Resize4、ColorJitter5、ToTensor6、RandomHorizontalFlip7、Normalization8、AssignGTtoDefaultBox前言 原论文 根据原论文&#xff0c;我们需要处理的有以下&#xff1a; data_transform {"train": transforms.Com…

vue2.x中使用vuex

Vuex是什么&#xff1f; Vuex是一个专门为Vue.js应用程序开发的状态管理模式。它采用集中式存储来管理应用程序中所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。Vuex也被集成到了Vue的官方调试工具vue-devtools中&#xff0c;提供了诸如零配置…

Java:使用Java功能确保应用程序安全的方法

与添加新功能一样重要的是&#xff0c;应用程序开发人员需要开始更加重视他们设计的应用程序的安全性。毕竟&#xff0c;更多的应用程序功能意味着更多的数据驻留在应用程序中。如果没有适当的安全控制&#xff0c;这些数据很容易被入侵者窃取。Java是目前世界上最安全、最流行…

如何去阅读源码,我总结了18条心法

在聊如何去阅读源码之前&#xff0c;先来简单说一下为什么要去阅读源码&#xff0c;大致可分为以下几点原因&#xff1a;最直接的原因&#xff0c;就是面试需要&#xff0c;面试喜欢问源码&#xff0c;读完源码才可以跟面试官battle提升自己的编程水平&#xff0c;学习编程思想…

不要慌,我们谈一谈如何用好 ChatGPT

别人贪婪时我恐惧&#xff0c;别人恐惧时我贪婪。 ——巴菲特 ChatGPT 火了&#xff0c;技术领域的社交媒体、自媒体几乎被 ChatGPT 刷屏&#xff0c;这些内容当中最让人惶恐不安的是我们是否会被 AI 取代之类的文章。 比如以下几个文章标题&#xff1a; 《ChatGPT可能马上…

Transformer结构解读

咱们还是照图讨论&#xff0c;transformer结构图如下&#xff0c;本文主要讨论Encoder部分&#xff1a;图一一、首先说一下Encoder的输入部分&#xff1a;在NLP领域&#xff0c;个人理解&#xff0c;这个inputs就是我们的句子分词之后的词语&#xff0c;比如“我&#xff0c;喜…

符号让人疯狂

符号让人疯狂 判断背了个LV符号的包就想可能有钱 趣讲大白话&#xff1a;人是通过符号区分生活的 聪明人想想&#xff1a;能超越或摆脱符号依赖吗&#xff1f; *********** 信息社会加速符号的传递和创造 我们已经被各种信息传递的符号淹没 信息符号的筛选成了人的主要工作 再…

GRB非隔离系列宽电压输入负高电压输出 电压控制型

特点● 效率高达70%以上● 1*2英寸标准封装● 单电压负输出● 价格低● 电压控制,输出电压随控制电压变化线性变化● 工作温度: -40℃~85℃● 阻燃封装&#xff0c;满足UL94-V0 要求● 温度特性好● 可直接焊在PCB 上应用GRB 系列模块电源是一种DC-DC升压变换器。该模块电源的输…

十、Linux文件 - fread函数讲解

目录 1.fread函数讲解 2.fread函数实战 1.fread函数讲解 从文件中读入数据到指定的地址中 函数原型&#xff1a; size_t fread(void*buff , size_t size, size_t count , FILE* stream) /* * description :对已打开的流进行数据读取 * param ‐ ptr &#xff1a;指向 数据块的…