ts中的泛型

82 阅读3分钟

1.泛型是什么

泛型就是当你在写公用的组件或utils时,会不确定消费者(业务侧的数据类型),此时可以使用泛型来定义。

2.泛型的用途

在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。 不同于使用 any,它不会丢失信息。

eg.创建一个函数会返回任何传入它的值.

function identity(arg: any): any { return arg; }

使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。

因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。

function identity<T>(arg: T): T { return arg; }

我们定义了泛型函数后,可以用两种方法使用。 第一种是,传入所有的参数,包含类型参数:

let output = identity<string>("myString"); // type of output will be 'string'

第二种方法更普遍。利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型:

let output = identity("myString"); // type of output will be 'string'

3.泛型在函数中的使用(泛型类型)

普通函数

见上面例子

匿名函数

const identit = <T>(arg:T):T => arg

可见,匿名函数配合箭头函数可以简化代码。

4.泛型在接口interface中的使用

interface GenericIdentityFn<T> 
{ 
(arg: T): T; 
} 
function identity<T>(arg: T): T { return arg; } 
let myIdentity: GenericIdentityFn<number> = identity;

泛型参数也可以定义多个

export interface AxiosResponse<T = any, D = any> {
  data: T;
  status: number;
  statusText: string;
  headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
  config: AxiosRequestConfig<D>;
  request?: any;
}

5.泛型在类中的使用

泛型类看上去与泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面。

class GenericNumber<T> { 
    zeroValue: T; add: (x: T, y: T) => T; 
} 
let myGenericNumber = new GenericNumber<number>(); 
myGenericNumber.zeroValue = 0; 
myGenericNumber.add = function(x, y) { return x + y; };

泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。

6.泛型约束:当泛型被定义了约束时就不再适用于任意类型了

创建一个包含 .length属性的接口,使用这个接口和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(3); // Error, number doesn't have a .length property

我们需要传入符合约束类型的值,必须包含必须的属性

loggingIdentity({length: 10, value: 3});

7.在泛型约束中使用类型参数(使用keyof约束对象)

你可以声明一个类型参数,且它被另一个类型参数所约束。 比如,现在我们想要用属性名从对象里获取这个属性。 并且我们想要确保这个属性存在于对象 obj上,因此我们需要在这两个类型之间使用约束。

image.png