Skip to content

什么是泛型(generics)?

所谓泛型简单理解就是: 宽泛的类型, 在定义的时候不知道是什么类型, 在使用的时候再指定类型

为什么要使用泛型?

举个例子: 实现一个填充数组函数的方法, 可以传入 2 个参数, 第一个参数代表填充的个数, 第二个参数代表要填充的值, 第二个参数的值可以是任意类型, 且必须有类型约束

typescript
// 如果这样子实现的话, 第二个参数没有约束类型
// function fillArray(count: number, data: any): any[] {}

// 传入的 <T> 是什么类型, 那么 result 的 Array<T> 就是什么类型
function fillArray<T>(count:number, data:<T>): Array<T> {
  const result:Array<T> = []; // Array<T> 也可以使用 T[] 这种形式
  for (let i = 0; i< count; i++) {
    result.push(data);
  }
  return result;
}

fillArray(5, "hello");
// 也可以手动指定泛型的类型 fillArray<string>(5, "hello")

泛型继承

  • 要求传入的第二个参数必须要有 length 属性
typescript
interface ILength {
 length: number;
}

function fillArray<T extends ILength>(count:number, data:<T>): Array<T> {
  const result:Array<T> = [];
  for (let i = 0; i< count; i++) {
    result.push(data);
  }
  return result;
}

fillArray(3, "1"); // 字符串有 length 属性
fillArray(3, [1]); // 数组也有 length 属性
fillArray(3, { length: 1, hello: "world" });// 传入的对象有 length 属性
fillArray(3, { hello: "world" }); // 传入对象没有 length 属性, 所以会报错
fillArray(3, 1); // 数字没有 length 属性, 所以会报错

在类中使用泛型(泛型类)

typescript
interface ICacheMaanger {
  caches: Array<any>;
  add(val: any): void;
  all(): any[];
}

// 不使用泛型 -----
class NumberCacheMgr implements ICacheManager {
  caches: number[] = [];
  add(val: number): void {
    this.caches.push(val);
  }
  all(): number[] {
    return this.caches;
  }
}
class StringCacheMgr implements ICacheManager {
  caches: string[] = [];
  add(val: string): void {
    this.caches.push(val);
  }
  all(): string[] {
    return this.caches;
  }
}

// 以上代码可以发现, 除了类型不一样, 其他所有的处理都是一样的
// 此时, 就可以使用泛型, 在使用的时候再确定类型

// 使用泛型 -----
class CacheManager implements ICacheManager {
  private caches: T[] = [];
  add(val: T): void {
    this.caches.push(val);
  }
  all(): T[] {
    return this.caches;
  }
}

const numCacheMgr = new CacheManager<number>();
numCacheMgr.add(1);
numCacheMgr.add(3);
// numCacheMgr.add("hello"); // 报错

const strCacheMgr = new CacheManager<string>();
strCacheMgr.add('hello');
strCacheMgr.add('world');
// strCacheMgr.add(true); // 报错

const userCacheMgr = new CacheManager<{ id: number; email: string }>();
userCacheMgr.add({ id: 1001, email: 'tom@qq.com' });
userCacheMgr.add({ id: 1002, email: 'jerry@qq.com' });

类型别名使用泛型

typescript
type Position<T> = { x: T; y: T };
const p1: Position<string> = { x: '10px', y: '10px' };
const p2: Position<number> = { x: 30, y: 50 };

Released under the MIT License.