ts中的泛型

发布时间 2023-08-01 21:51:26作者: yunChuans

在 TypeScript 中我们会使用泛型来对函数的相关类型进行约束 这里的函数 同时包含 class 的构造函数 因此 一个类的声明部分 也可以使用泛型 那么 什么是泛型? 如果通俗的理解泛型呐?

什么是泛型

泛型 (Generics) 是指在定义函数 接口或类的时候 不预先指定具体的类型 而在使用的时候在指定类型的一种特性

通俗的解释 泛型是类型系统中的 参数 主要作用是为了类型的重用 从上面定义可以看出 它只会用函数 接口和类中 它和 js 程序中的函数参数是两个层面的事物 (虽然意义是相同的) 因为 typescript 是静态类型系统 是在 js 进行编译时进行类型检查的系统 因此 泛型这种参数 实际上是编译过程中的运行时使用 之所以称它为参数 是因为它具备和函数参数一模一样的特性

泛型函数

目标:声明一个函数 接收一个参数 接收什么参数返回什么值

function getValue<T>(value: T): T {
	return value;
}

getValue<string>("hello");
getValue<number>(100);

//  泛型实参可以忽略   你传递的参数的类型就是要传递的泛型的类型
echo("hello")

泛型类

需求:通过类创建对象 对象的 key 属性可以是字符串可以是数值 对象的 value 属性可以是 字符串可以是数值

{key: string, value: string}
{key: number, value: number}
class StringKeyValuePair {
	constructor(public key: string, public value: string){}
}

class NumberKeyValuePair {
	constructor(public key: number, public value: number){}
}
class KeyValuePair<K, V> {
	constructor(public key: K, public value: V){}
}

泛型接口

需求:创建 fetch 方法用获取数据 当获取用户数据时 fetch 方法的返回值类型为用户 当获取产品数据时 fetch 方法的返回值类型为产品 不沦是用户数据还是产品数据都要被包含在响应对象中

interface MyUserResponse {
	data: User;
}

interface MyProductResponse {
	data: Product;
}
interface MyResponse<T> {
	data: T | null;
}

function fetch<T>(): MyResponse<T> {
	return {data: null};
}

interface User {
	username: string;
}

interface Product {
	title: string;
}

fetch<User>().data?.username;
fetch<Product>().data?.title;

泛型约束

泛型约束是指对泛型参数的范围进行约束 就是说虽然类型可以被当做参数传递 但是传递的类型不能是随意的想传什么就传什么 通过泛型约束可以限制能够传递的类型的范围

// 限制类型 T 的范围  就是说  T  的类型要么是字符串要么是数值  其他的是不可以的
class StringOrNumberArray<T extends string | number> {
	constructor(public collection: T[]) {}
	get(index: number): T {
		return this.collection[index];
	}
}

new StringOrNumberArray<string>(["a", "b"])
new StringOrNumberArray<number>([100, 200])

// 类型  boolean  不满足约束  string | number
// new StringOrNumberArray<boolean>([true, false]);
function echo<T extends string | number>(value: T): T {
	return value;
}
echo<string>("hello")
echo<number>(100)
echo<boolean>(true)
interface Person {
	name: string;
}

function echo<T extends Person>(value: T): T{
	return value;
}
echo<Person>({name: "张三"})
class Person {
	constructor(public name: string) {}
	
}
class Custom extends Person {}
function echo<T extends Person>(value: T): T {
	return value;
}

echo<Person>(new Person("张三"));
echo<Custom>(new Custom("李四"));
interface Printable {
	print(): void;
}

function echo<T extends Printable>(target: T) {
	target.print()
}
class Car {
	print() {}
}
class Hourse {
	print() {}
}
echo<Car>(new Car());
echo<Hourse>(new Hourse());

继承泛型类

class Store<T> {
	protected _objects: T[] = [];
	add(obj: T) {
		this._objects.push(obj);
	}
}

interface Product {
	name: string;
	price: number;
}
const store = new Store<Product>();
class CompressibleStore<T> extends Store<T> {}
new CompressibleStore<Product>();
clsaa ProductStore extends Store<Product> {}