TypeScript 之 泛型、泛型约束

1,130 阅读1分钟

具有以下特点的数据类型叫泛型

特点一:定义时不明确使用时必须明确成某种具体数据类型的数据类型。【泛型的宽泛】【定义时不明确类型,使用时必须明确类型, 】

特点二:编译期间进行数据类型检查的数据类型。【泛型的严谨】【一旦泛型没有给具体的值会抛错误】

class 类名<泛型形参类型> 泛型形参类型一般有两种表示:1. A-Z 任何一个字母 2. 语义化的单词来表示,绝大多数情况 ,泛型都是采用第一种形式表示,如下:

class ArrayList<T>{
  array: Array<T>
  add(data: T) {
     ...
  }
  ...
}

泛型的基本使用

interface Ref<T> {
  value: T
}

let ref: Ref<number> = {
  value: 23
}

type Student = { name: string, age: number };
let ref2: Ref<Student> = {
  value: { name: 'wangwu', age: 23 }
}

console.log(ref2.value.name);

keyof 表示获取一个类或者一个对象类型 或者一个接口类型的所有属性名[key]组成的联合类型。


class ArrayList<T = any> {
  arr: Array<T>
  index: number = 0
  constructor() {
    this.arr = [];
  }
  add(ele: T) {
    this.arr[this.index++] = ele;
  }
  get(index: number) {
    return this.arr[index]
  }
}

let arrlist = new ArrayList<string>();
arrlist.add("Abc");
console.log(arrlist);
console.log(arrlist.get(0));

let arrlist2 = new ArrayList<{ userName: string; age: number }>();
arrlist2.add({ userName: 'wangwu', age: 12 });
console.log(arrlist2);

泛型约束


class Order {
  orderid!: number;
  ordername!: string;
  static count: number;
  printOrd() { }
  static getCount() { }
};

// type OrdIdType = Order['orderid'];

// type OrdInstanceAttrNames = keyof Order;


type InstancePropKeys<T extends object> = keyof T;
type OrdPropKeys = InstancePropKeys<Order>;

使用extends keyof 约束泛型类型

class ObjectRefImpl<T extends object, K extends keyof T> {
  public readonly __v_isRef = true;

  constructor(private readonly _object: T, private readonly _key: K) { }

  get value() {
    return this._object[this._key];
  }

  set value(newVal) {
    this._object[this._key] = newVal;
  }
}

type ObjTyp = { username: string; age: 23 };
type ObjKeysType<T extends object, K> = K extends keyof T ? K : never
type TestObjKeysTyp = ObjKeysType<ObjTyp, "username" | "age" | "address">; // TestObjKeysTyp 的类型还是 "username" | "age"

let obj = new ObjectRefImpl<ObjTyp, "age">({ "username": 'list', "age": 23 }, "age");
console.log("obj.value:", obj.__v_isRef, obj.value);

// 不同的应用方式
let obj = new ObjectRefImpl({ "username": 'list', "age": 23 }, "username");