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

范型约束

T extends U 保证了 T是 U的子类或者T就是U的类

  1. interface length{
  2. length:number;
  3. }
  4. function add<T extends length>(arg:T):number {
  5. return arg.length;
  6. }
  1. class O {
  2. n: string
  3. }
  4. class Person extends O {
  5. name: string
  6. }
  7. class Student extends Person {
  8. age: number
  9. }
  10. function test<T extends Person>(num: T) {
  11. console.log(num);
  12. }
  13. // 此时是 Person的子类
  14. test({ name: '1', age: 2, n: '1' });
  15. // 报错
  16. // test(new O());
  17. test(new Person());
  18. test(new Student());

泛型参数的默认类型

可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。

  1. function createArray<T = string>(length: number, value: T): Array<T> {
  2. let result: T[] = [];
  3. for (let i = 0; i < length; i++) {
  4. result[i] = value;
  5. }
  6. return result;
  7. }

范型接口

  1. interface CreateArrayFunc {
  2. <T>(length: number, value: T): Array<T>;
  3. }
  4. createArray = function<T>(length: number, value: T): Array<T> {
  5. let result: T[] = [];
  6. for (let i = 0; i < length; i++) {
  7. result[i] = value;
  8. }
  9. return result;
  10. }

可以把泛型参数提前到接口名

  1. interface CreateArrayFunc<T> {
  2. (length: number, value: T): Array<T>;
  3. }
  4. let createArray: CreateArrayFunc<any>;
  5. createArray = function<T>(length: number, value: T): Array<T> {
  6. let result: T[] = [];
  7. for (let i = 0; i < length; i++) {
  8. result[i] = value;
  9. }
  10. return result;
  11. }

泛型类

  1. class GenericNumber<T> {
  2. zeroValue: T;
  3. add: (x: T, y: T) => T;
  4. }
  5. let myGenericNumber = new GenericNumber<number>();
  1. // 范型类
  2. class GenericClass<T> {
  3. public name: T
  4. r<E>(str: T = null) {
  5. console.log(str);
  6. }
  7. }
  8. // 范型接口
  9. interface GenericInterface<T> {
  10. name: T
  11. }
  12. //范型方法(函数)
  13. function names<T>(): void {
  14. }
  15. // 箭头函数的范型方法
  16. <T>() => {
  17. }
  18. const g: GenericClass<string> = new GenericClass()
  19. g.r<string>()

keyof 约束

在范型中则使用 extends keyof约束

  1. // keyof Studen 相当于 是 Student的联合类型 'name' | 'n' | 'age'
  2. function test<T extends Person, U extends keyof Student>(num: T, key: U) {
  3. console.log(num);
  4. }
  5. // 此时是 Person的子类
  6. test({ name: '1', age: 2, n: '1' }, 'name');
  7. // 报错
  8. // test(new O());
  9. test<Person, 'name' | 'n'>(new Person(), 'name');
  10. test<Student, 'name' | 'n' | 'age'>(new Student(), 'age');
  11. // 相当于了 Person的联合类型
  12. const num: keyof Person = 'name'