typescript 泛型工具 infer

55 阅读2分钟

Partial:接收一个泛型,把它的所有属性转为可选的

interface User {
  name: string;
  age: number;
}
//type PartialUser = {
//  name?: string;
//  age?: number;
//}
type PartialUser = Partial<User>;
//实现原理
type CoustomPartial<T> = {
  [key in keyof T]?: T[key];
};

Required:接收一个泛型,把它的所有属性转为必选的

interface User {
  name?: string;
  age?: number;
}
// type RequiredUser = Required<User>;
//实现原理
type CoustomRequired<T> = {
  [key in keyof T]-?: T[key];
};
type RequiredUser = CoustomRequired<User>;

Pick:提取部分属性。接收两个参数,第一个是泛型,第二个是要提取的属性(支持联合类型)

interface User {
  name?: string;
  age?: number;
  sex?: string;
}
// type Test = Pick<User, "age" | "name">;
//实现原理
type CoustomPick<T, K extends keyof T> = {
  [key in K]: T[key];
};
type Test = CoustomPick<User, "age" | "name">;

Exclude:排除部分属性。接收两个参数(联合类型),

type Test = Exclude<1 | 2 | 3, 1>;
//实现原理  never在联合类型中是会被排除的
type CoustomExclude<T, K> = T extends K ? never : T;
type Test = CoustomExclude<1 | 2 | 3, 1>;

Omit:排除部分属性。接收两个参数,第一个是泛型,第二个是要排除的属性(支持联合类型)

type Test = Exclude<1 | 2 | 3, 1>;
//实现原理  never在联合类型中是会被排除的
type CoustomExclude<T, K> = T extends K ? never : T;
type Test = CoustomExclude<1 | 2 | 3, 1>;

Record:约束对象的key以及value,接收两个泛型

type Key = "a" | "b" | "c"; //key 不能少
type Value = "阿" | "松" | "大"; //value 可以
const obj: Record<Key, Value> = {
  a: "阿",
  b: "松",
  c: "松",
};
//支持嵌套写法
const obj1: Record<Key, Record<Key, Value>> = {
  a: { a: "阿", b: "松", c: "松" },
  b: { a: "阿", b: "松", c: "松" },
  c: { a: "阿", b: "松", c: "松" },
};
//原理实现
//对象的key只能是string number symbol
type ObjKey = keyof any; //语法糖
type CustomRecord<K extends ObjKey, T> = {
  [key in K]: T;
};
const obj2: CustomRecord<Key, Value> = {
  a: "阿",
  b: "松",
  c: "松",
};

ReturnType:获取函数类型的返回值

const fn = () => [1, "2", false];
type arrType = ReturnType<typeof fn>;
//实现原理
type CusiomReturnType<F extends Function> = F extends (
  ...args: any[]
) => infer Res
  ? Res
  : never;
type arrType1 = CusiomReturnType<typeof fn>;

infer:用来推导泛型参数,infer声明只能出现在extends子语句中

interface User {
  name: string;
  age: number;
}
type PromiseType = Promise<User>;
type GetPromiseType<T> = T extends Promise<infer U> ? U : T;
type T = GetPromiseType<PromiseType>;

infer协变:产生协变会返回联合类型

let obj = {
  name: "账户",
  age: 19,
};
type Bar<T> = T extends { name: infer U; age: infer U } ? U : T;
type T = Bar<typeof obj>;

infer逆变:出现在函数的参数上面,逆变返回的是交叉类型,目的是为了保证参数的一致性

type Bar<T> = T extends {
  name: (x: infer U) => void;
  age: (x: infer U) => void;
}
  ? U
  : T;
//type T = never  相当于type a = string & number
type T = Bar<{ name: (x: string) => void; age: (x: number) => void }>;