泛型是一种传递类型的方式,是一种类型占位符,这种类型占位符告诉我们的(function、class或interface)我们在调用它时想要使用什么类型
const obj = {
name: 'zhangSan',
age: 18
}
function getValue<T,k extends keyof T>(obj: T,key: K):T[K] {
return T[K]
}
getValue(obj,'name') // zhangSan
T
:代表Type,在定义泛型时通常用作第一个类型变量名。K
:表示对象中的键类型V
:表示对象中的值类型E
:表示元素类型// 处理单个参数
function fn1<T>(arg:T):T {
return arg
}
fn1(123) // 123
fn1('zhangSan') // ‘zhangSan’
// 处理多个参数
function fn2<T, U>(arg1: T,arg2: U)[T,U] {
return [arg1, arg2]
}
fn2(123,'zhangSan') // [123,'zhangSan']
我们在使用可以有两种方式指定类型
// 这里指定了 T 的类型为 string
fn1<string>('zhangSan') // 'zhangSan'
// 这里没有指定 T 的类型,但是 TS 可以通过实参的类型(string)推到出 T 的类型为 string
fn1('zhangSan') // 'zhangSan'
使用 type
定义函数类型
type fn = <T>(arg: T) => T
const text: fn = function getObjValue(arg) {
return arg
}
使用 interface
定义函数类型
interface Fn<T> {
(arg: T) : T
}
语法:
// 使用 type 定义了 fn 函数,fn 函数的泛型默认是 number
type fn<T = number> = (arg: T) => T
// 定义一个函数打印参数的 length
function printLnegth<T>(arg:T) {
console.log(arg.length) // 这样写会报错,因为泛型 T 并没有 length 属性
}
这时可以通过 interface 来约束泛型
interface LengthProps {
length: number
}
function printLnegth<T extends LengthProps>(arg:T) {
console.log(arg.length)
}
其中
,让泛型继承了接口 LengthProps
,使得泛型T
具有了 length
属性,从而使得函数参数具有了 length
属性
interface KeyValue<T, U> {
key: T,
value: U
}
const k1: KeyValue<number, string> = {key: 123, value: 'zhangSan'}
cosnt k2: KeyValue<string,number> = {key: 'zhangSan', value: 123}
// 之前定义数组
const arr1: number[] = [1,2,3]
// 通过泛型约束数组
const arr2: Array<number> = [1,2,3]
Partial
:将类型T的所有属性转换为可选属性。
interface Person {
name: string;
age: number;
}
const partialPerson: Partial<Person> = {
name: 'John',
};
// partialPerson的类型为 Partial,即 { name?: string; age?: number; }
Required
:将类型T的所有属性转换为必选属性。。interface Person {
name?: string;
age?: number;
}
const requiredPerson: Required<Person> = {
name: 'John',
age: 25,
};
// requiredPerson的类型为 Required,即 { name: string; age: number; }
Readonly
:将类型T的所有属性转换为只读属性。
interface Person {
name: string;
age: number;
}
const readonlyPerson: Readonly<Person> = {
name: 'John',
age: 25,
};
// readonlyPerson的类型为 Readonly,即 { readonly name: string; readonly age: number; }
Record
:创建一个类型,其中键为类型K中的每个属性,并将它们映射到类型T。type Weekday = 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday';
const schedule: Record<Weekday, string> = {
Monday: '9 AM - 5 PM',
Tuesday: '9 AM - 5 PM',
Wednesday: '9 AM - 5 PM',
Thursday: '9 AM - 5 PM',
Friday: '9 AM - 3 PM',
};
// schedule的类型为 Record,即 { Monday: string; Tuesday: string; Wednesday: string; Thursday: string; Friday: string; }
Exclude
:从类型T中排除可以赋值给类型U的所有属性。type Numbers = 1 | 2 | 3 | 4 | 5;
type EvenNumbers = Exclude<Numbers, 1 | 3 | 5>;
// EvenNumbers的类型为 2 | 4
Omit
:从类型T中排除指定属性K。interface Person {
name: string;
age: number;
address: string;
}
type PersonWithoutAge = Omit<Person, 'age'>;
// PersonWithoutAge的类型为 { name: string; address: string; }
Pick
:从类型T中选择指定属性K。interface Person {
name: string;
age: number;
address: string;
}
type PersonNameAndAddress = Pick<Person, 'name' | 'address'>;
// PersonNameAndAddress的类型为 { name: string; address: string; }
NonNullable
:从类型T中排除null和undefined。type Value = string | null | undefined;
const nonNullableValue: NonNullable<Value> = 'Hello';
// nonNullableValue的类型为 string
ReturnType
:获取函数类型T的返回类型。function greet(name: string): string {
return `Hello, ${name}!`;
}
type GreetReturnType = ReturnType<typeof greet>;
// GreetReturnType的类型为 string
Parameters
:获取函数类型T的参数类型。function greet(name: string, age: number): string {
return `Hello, ${name}! You are ${age} years old.`;
}
type GreetParameters = Parameters<typeof greet>;
// GreetParameters的类型为 [string, number]
泛型
指的是在定义函数、接口或者类的时候,不预先指定具体的类型,而是在使用的时候在指定类型。泛型
中的 T
就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出。