泛型
https://www.typescriptlang.org/docs/handbook/2/generics.html
指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。
没引入泛型之前,函数可以用重载方式来解决
function add(x: string, y: string): string;
function add(x: number | string, y: number | string): number | string {
if (typeof x === 'string' && typeof y === 'string') {
return x + y
} else if (typeof x === 'number') {
return x
}
}
const add1 = add(1, 2);
const add2 = add('1', '2');
const add3 = add('1', '2');
console.log(add1);
console.log(add2);
out
1
12
使用函数泛型
使用<>
,调用的时候<>
填入对应的类型
function add<E>(x: E, y: E): E {
if (typeof x === 'string' && typeof y === 'string') {
return <E><unknown>(x + y);
} else if (typeof x === 'number' && typeof y === 'number') {
return <E><unknown>(x + y)
}
return x;
}
const add1 = add<number>(11, 2);
// const add2 = add<string>('11', 2); // 类型“number”的参数不能赋给类型“string”的参数。
const add3 = add<string>('11', '2');
console.log(add1);
console.log(add3);
out
13
112
多个泛型参数的函数
function swap<K, V>(x: K, y: V): [V, K] {
return [y, x];
}
const add1 = swap<string, number>('11', 2);
console.log(add1);
out
[ 2, '11' ]
泛型接口
定义接口时, 为接口中的属性或方法定义泛型类型
使用接口时, 再指定具体的泛型类型
interface BaseService<T> {
add: (t: T) => void;
getById: (id: number) => T | null;
}
class User {
id?: number;
name: string;
constructor(name: string) {
this.name = name;
}
}
class UserService implements BaseService<User>{
list: User[] = [];
add(user: User): void {
if (user) {
user = { ...user, id: Date.now() }
this.list.push(user);
}
};
getById(id: number): User | null {
let user = this.list.find(e => e.id === id);
if (user)
return user;
else
return null;
};
}
const u = new UserService();
u.add(new User('张三'));
u.add(new User('李四'));
console.log(u.list);
let us = u.getById(1632645862078);
console.log(us);
out
[
{ name: '张三', id: 1632645922803 },
{ name: '李四', id: 1632645922803 }
]
null
泛型类
在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型
class Calculator<T>{
add!: (x: T, y: T) => T;
}
let myCalculatorN = new Calculator<number>();
myCalculatorN.add = function (x, y) {
return x + y;
}
console.log(myCalculatorN.add(2, 3));
let myCalculatorS = new Calculator<string>();
myCalculatorS.add = function (x, y) {
return x + y;
}
console.log(myCalculatorS.add('2', '3'));
out
5
23
泛型约束
对泛型参数取 length
属性, 会报错, 因为这个泛型根本就不知道它有这个属性
// 没有泛型约束
function ugly <T>(x: T): void {
// console.log(x.length) // error 类型“T”上不存在属性“length”
}
使用泛型约束来实现
interface BaseLength {
length: number;
}
// 指定泛型约束
function ugly<T extends BaseLength>(x: T): void {
console.log(x.length)
}
ugly<string>('2');
//ugly<number>('2'); // 类型“number”不满足约束“BaseLength”。
out
1