feng xiaohan

泛型

可以理解为是动态类型,在定义函数时不明确类型,而是采用泛型(占位符),在使用时泛型会自动推断出相应类型。它主要是为了解决一些具有相同逻辑的函数但传入参数不同,而导致的代码逻辑重复性高的问题。

基本使用

函数泛型

function fun1<T>(a: T, b: T): Array<T> {
  // <>定义泛型,里面可以随意
  return [a, b];
}

fun1(1, 2); // fun1<number>(1,2) 写全是这样,但是ts能类型推断出来,所以可以不用写完整
fun1("1", "2");
fun1(false, true);

type 泛型

type A<T> = string | number | T;
let a: A<null> = null;

interface 泛型

interface B<T> {
  msg: T;
}

let data: B<number> = {
  msg: 1,
};

联合泛型

function add<T, K>(a: T, b: K): Array<T | K> {
  return [a, b];
}
add(1, false);

泛型也可以设置默认值:

function add<T = number, K = number>(a: T, b: K): Array<T | K> {
  return [a, b];
}

应用

调用接口时使用泛型:

const axios = {
  get<T>(url: string): Promise<T> {
    return new Promise((resolve, reject) => {
      let xhr: XMLHttpRequest = new XMLHttpRequest();
      xhr.open("GET", url);
      xhr.onreadystatechange = () => {
        if (xhr.readyState == 4 && xhr.status == 200) {
          resolve(JSON.parse(xhr.responseText));
        }
      };
      xhr.send(null);
    });
  },
};
interface Data {
  message: string;
  code: number;
}
axios.get<Data>("./data.json").then((res) => {
  console.log(res); // res能访问Data里定义的属性
});

泛型约束(extends,内有 keyof)

使用泛型约束来控制泛型的类型范围。通过再泛型的后面跟一个extends再跟一个约束的泛型类型来进行约束:

function add<T extends number>(a: T, b: T) {
  return a + b;
}
add(1, 2); // 这样对于add()来说约束了参数相加的类型,避免了不能相加的类型
  • 约束传入参数具有length属性:

    interface Len {
      length: number;
    }
    function fun<T extends Len>(a: T) {
      a.length;
    }
    fun("dsadas");
    fun([1, 2, 3]);
    // fun(123) 没有length,不支持
    // fun(true) 没有length,不支持
    
  • 约束对象的 key:

    约束传入的值为某个对象的属性。

    let obj = {
      name: "张三",
      age: 18,
    };
    function ob<T extends object, K extends keyof T>(obj: T, key: K) {
      return obj[key]; // 如果不对K进行约束,则key会报错
    }
    ob(obj, "name");
    

    keyof:将对象类型里的 key 推断成联合类型。

    type Key = keyof typeof obj; // type Key = "name" | "age"
    
  • 对对象类型里的 key(属性)添加可选 符号:

    interface Data {
      name: string;
      age: number;
      sex: string;
    }
    type Options<T extends object> = {
      [Key in keyof T]?: T[Key]; // 定义一个Key(任意)使用in操作符再联合类型T中循环
    };
    type B = Options<Data>;