4

泛型

声明: 这篇文章可能没有任何意义,因为代码实例都是官网上的

本人只是边学习,边记录过程,以及进行改写。如有不明,可直接移步官方文档

初识泛型

官方的两个例子

例子一:我们使用any类型来定义函数:输入任意类型的参数,返回任意类型的值

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

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

例子二:改写一下

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

console.log(identity(100)); // 100
此时我们只能传入number类型的数据 ,返回的也是number

但是,我们要的效果是,传入一种数据类型的参数,返回的只能是那种,可我们将他固定为number显然不合适。比如我们要求string也适合

此时我们引入 类型变量 T
function identity<T>(arg: T): T {
  return arg;
}

此时我们可以想获取自己想要的任何类型 如下:我们传入的参数是string类型,返回的也是string类型

let id: string = identity<string>("hello world");
console.log(id); // hello world

也可以直接使用类型推断,简略代码

// let id:number = identity<number>(101010);
let id = identity(101010); // // 等同于上一行代码 类型推断 
console.log(id)

个人觉得还是长一点具有可读性,不需要编译器进行类型推断。既然使用了typescript,自然要让它看起来更严格。

使用泛型变量

泛型的数组, 打印它的长度
function fun<T>(arg: T[]): void {
  console.log(arg.length)
}
// fun<number>([1,2,4]); // 3
fun<string>(['a','b','c', 'd']); // 4

函数类型

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

let myIdentity: <T>(arg: T) => T = identity;

等同于js中的

function identity(arg) {
    return arg;
}
let myIdentity = identity;
其实就是函数声明和使用

或许下面这样写更让我明白

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

let myIdentity: {<T>(arg: T): T} = identity;

泛型的接口

上面一个列子

看标红处

其实这个完全可以用接口去声明。

官方代码

字面量拿出来做为一个接口
interface GenericIdentityFn {
  <T>(arg: T): T;
}

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

let myIdentity: GenericIdentityFn = identity;

再者,把泛型参数当作整个接口的一个参数
interface GenericIdentityFn<T> {
    (arg: T): T;
}

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

let myIdentity: GenericIdentityFn<number> = identity;
等同于下面这个代码
interface GenericIdentityFn<T> {
    (arg: T): T;
}

let myIdentity: GenericIdentityFn<number> = function <T>(arg: T): T {
  return arg;
}
就是函数的声明

使用这个函数,用变量来接受这个函数的返回值

// let id: string = myIdentity('102'); // Argument of type '"102"' is not assignable to parameter of type 'number'.
let id: number = myIdentity(102);
console.log(id)

泛型类

class GenericNumber<T> {
  zeroValue: T;
  add: {(x: T, y: T): T}; // 方法名 参数 返回值类型
}

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

let sum = myGenericNumber.add(1,3);
console.log(sum); // 4

泛型约束

// 泛型约束
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});

邢走在云端
303 声望25 粉丝

you async, i await.