# 泛型
是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。与any相比,使用泛型的优势是会保留参数类型。
# 为什么需要泛型
例如有一个identity函数, 这个函数会返回任何传入它的值。
function identity(arg: number): number {
return arg;
}
如上,如果使用基本变量的话。那么只能规定一种变量来作为值类型。或者,我们使用any类型来定义函数:
function identity(arg: any): any {
return arg;
}
我们要求传入的类型和返回的类型相同,any是任何类型,就无法达到要求。
# 泛型语法
function identity <T>(arg:T) : T {
return arg
}
# 调用
let result = identity<string>("myString");
let result = identity<number>(1);
明确的指定了T的类型,并做为一个参数传给函数,使用了<>括起来。
通常我们利用类型推论-即编译器会根据传入的参数自动地帮助我们确定T的类型:
let result = identity("myString"); // type of result will be 'string'
# 泛型变量
现在假设我们向函数传入泛型T,返回T类型的数组
function loggingIdentity<T>(arg: T): T[] {
let list:T[] = []
for(let i = 0; i < 3; i++){
list.push(arg)
}
return list
}
此处的T作为一个变量,当做类型的一部分使用,而不是整个类型,增加了灵活性。
# 泛型约束
定义一个接口来描述约束条件。使用这个接口和extends关键字
来实现约束。
比如我们定义传入的参数类型,一定有某个属性
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
执行
loggingIdentity({length: 10, value: 3});
# 泛型接口
定义接口的时候,我们也可以使用泛型
interface A<T> {
data: T
}
const Info: A<string> = {data: '1'}
console.log(Info.data) // "1"
# 泛型类
泛型也可以定义类
class clacArray<T>{
private arr: T[] = [];
add(value: T) {
this.arr.push(value)
}
getValue(): T {
let res = this.arr[0];
console.log(this.arr)
return res;
}
}
const res = new clacArray()
res.add(1)
res.add(2)
res.add(3)
res.getValue() //[1, 2, 3]
console.log(res.getValue) // 1
# 泛型常用字母
- T:代表Type,定义泛型时通常用作第一个类型变量名称
- K:代表Key,表示对象中的键类型;
- V:代表Value,表示对象中的值类型;
- E:代表Element,表示的元素类型;
# Pick
将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型。
interface Props {
name: string,
age: number,
sex: boolean
}
type nameProps = Pick<Props, 'name' | 'age'>
const info: nameProps = {
name: '小杜杜',
age: 7
}
从上述代码上来看, Props原本属性包括name、age、sex三个属性,通过 Pick我们吧name和age挑了出来,所以不需要sex属性
# Exclude
作用:将T类型中的U类型剔除。Exclude语法:Exclude<T, U>
// 数字类型
type numProps = Exclude<1 | 2 | 3, 1 | 2> // 3
type numProps1 = Exclude<1, 1 | 2> // nerver
type numProps2 = Exclude<1, 1> // nerver
type numProps3 = Exclude<1 | 2, 7> // 1 2
// 字符串类型
type info = "name" | "age" | "sex"
type info1 = "name" | "age"
type infoProps = Exclude<info, info1> // "sex"
使用
type A = string | number | boolean
type B = string | boolean | symbol
type C = string
type exc = Exclude<A, B>
// type exc = number
type exc2 = Exclude<A, C>
// type exc2 = number | boolean
# Extra
作用:将T 可分配给的类型中提取 U。与 Exclude相反,Extra语法:Extra<T, U>
type numProps = Extract<1 | 2 | 3, 1 | 2> // 1 | 2
# Omit
Omit<T, K> 的主要功能在于,从一个已有的对象类型 T 中排除指定的属性 K,进而创建一个新的对象类型
interface Props {
name: string,
age: number,
sex: boolean
}
type Props2 = Omit(Props, "sex") // { name: string, age: number}
Exclude 和 Omit 的主要区别在于它们处理类型的方式和侧重点,Exclude 是针对联合类型,用于排除一些特定成员类型,Omit 是针对对象类型,用于忽略或排除某些特定属性;