在前端开发中,大家入门ts其实是很简单的,只要掌握一些基本的类型知识就可以逐步的将js过渡到ts的应用,然而,当我们的项目很庞大复杂的时候,在开发过程中很容易将一些类型定义成any,这里主要介绍一下ts的高级类型,帮助大家更好的定义变量类型,从来减少any的使用。
泛型的介绍
泛型是强类型中比较重要的概念,使用泛型可以帮助我们提高代码的复用性,泛型是通过<>尖括号来表示的。尖括号中的字符被称作类型变量,用来表示类型,接下来看一下概念中的描述:
示例:
public testGenerics<T>(arg: T): T { // T仅仅是个占位符,只不过大家都约定俗成的用T来占位
return arg;
}
const str = this.testGenerics<string>('just test generics');
代码中的类型T,在没有调用testGenerics函数的时候是不确定的,只有在调用次方法之后,我们才能明确知道T代表的是什么类型,我们给他传入什么类型,他就给我们返回什么类型,这样数据就可以对应上了~
高级类型介绍
在实际开发中,大家可能比较常用一些基础类型,比如string、number、boolean等,但是当我们了解了一些高级类型后,我们可以定义更大复杂,更加灵活的接口类型。
1. 联合类型(|)
联合类型的规则和逻辑“或”是一致的,表示类型是连接多个类型中的任意一个
T | U
// demo
interface IPerson {
age: number;
gender: '女' | '男';
}
const person: Iperson = {
age: 25;
gender: '女'
}
2. 交叉类型(&)
交叉类型可以将多个类型合并成一个类型,写法和逻辑“与”相同
T & U
// demo 现在有两个类,我们可以通过交叉类型来实现一个新的属性的类型定义
interface IPerson {
age: number;
gender: string;
}
interface IJob {
title: string;
years: number;
}
const life: IPerson & IJob = {
age: 30,
gender: 'nv',
title: '开发',
years: 10,
};
3. 类型别名(type)
类型别名,它允许你为类型创建一个名字,这个名字就是类型的别名,从而你可以在多处使用这个别名,并且有必要的时候,你可以更改别名的值(类型),以达到一次替换,多处应用的效果,类型别名与声明变量的语法很类似,只需要把const,let换成type关键字即可。
type Alias = T | U
// demo
type sex = '女' | '男';
interface IPerson {
age: number;
gender: sex;
}
4. 类型索引(keyOf)
keyof 类似于 Object.keys ,用于获取一个接口中 Key 的联合类型
// demo
interface IPerson {
age: number;
gender: sex;
}
// 使用了keyOf后,只要IPerson修改了,type类型也会跟着自动修改
type personKeys = keyof IPerson;
//等价于
type personKeys = 'age' | 'gender';
5. 类型约束(extends)
extends主要是用来对泛型加以约束的,他不像class使用extends是为了达到继承的目的。
// demo
type BaseType = string | number | boolean;
public testGenerics<T extends BaseType>(arg: T): T {
return arg;
}
this.testGenerics('123'); // 成功
this.testGenerics({}); // 失败
// 根据传入的obj来约束key的值
function getValue<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
6. 条件类型(U?X:Y)
条件类型的语法规则和三元表达式一致,一般用于一些类型不确定的情况
T extends U ? X : Y // 如果T是U的子级 ,那么他的类型就是X,否则就是Y
type Extract<T, U> = T extends U ? T : never; // 如果T是U的子级,那么返回T,否则抛弃
interface ITeacher {
age: number;
gender: sex;
}
interface IStudent {
age: number;
gender: sex;
homeWork: string;
}
type CommonKeys = Extract<keyof ITeacher, keyof IStudent>; // "age" | "gender"
7. 类型映射(in)
in用来做类型映射,遍历已有接口的key或者遍历联合类型
type Test<T> = {
[P in keyof T]: T[P];
};
// keyof T 相当于 type ObjKeys = 'a' | 'b'
// P in ObjKeys 相当于执行了一次 forEach 的逻辑,遍历 'a' | 'b'
interface IObj {
a: string;
b: string;
}
type newObj = Test<IObj>;
工具泛型介绍
ts中还内置了许多工具泛型,接下来介绍一些常用的工具泛型
1. Partial
用于将一个接口的所有属性都设置成可选状态,执行步骤就是先通过keyof T,取出类型变量T的所有属性,然后通过in进行循环,最后在每个属性上加上?
type Partial<T> = {
[P in keyof T]?: T[P]
}
// demo
interface ITeacher {
age: number;
gender: sex;
}
const teacherA: Partial<ITeacher> = {age: 28}; // 此时用了Partial,即使不给gender赋值也不会报错
2. Required
Required的作用刚好与Partial相反,是将接口中的每个属性都改成必须的,主要区别就是将Partial中的?替换成-?
type Required<T> = {
[P in keyof T]-?: T[P]
}
3. Exclude
Exclude 的作用与上边介绍过的Extract刚好相反,如果 T 中的类型在 U 不存在,则返回,否则抛弃。
type Exclude<T, U> = T extends U ? never : T
//demo
interface ITeacher {
age: number;
gender: sex;
}
interface IStudent {
age: number;
gender: sex;
homeWork: string;
}
type ExcludeKeys = Exclude<keyof ITeacher, keyof IStudent>; // "homeWork"
4. Pick
Pick主要用于提取接口中的某几个属性,我们可以通过这个泛型提取接口的属性,从而生成一个新的属性
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
// demo
interface IStudent {
name: string
age: number
homework: string
}
type StudentA = Pick<IStudent, "name" | "age"> // 提取这个接口中的name和age属性
const zs: StudentA = {
name: 'zs',
age: 18
}
5. Omit
Omit 的作用刚好和 Pick 相反, 用来排除接口中的某些属性
type Omit<T, K extends keyof any> = Pick<
T, Exclude<keyof T, K>
>
// demo
interface IStudent {
name: string
age: number
homework: string
}
type StudentA = Omit<IStudent, "name"> // 排除掉这个接口中的name属性
const zs: StudentA = {
age: 18,
homework: '背诵课文'
}
总结
最近TypeScript发布了 4.0 的版本新增了很多功能,建议大家可以去更好的了解和掌握它,希望此篇文章可以帮助大家,让大家有所收获,减少甚至摆脱开发中的AnyScript~
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!