typeScript操作符

47 阅读4分钟

上一章:typeScript类型

extends

继承

继承父类接口的方法和属性

interface Person {
  name: string;
  age: number;
}
interface Student extends Person {
  score: number;
}
// Student: name/age/score

项目中调用后台接口经常碰到新增和编辑,编辑的参数一般只比新增多个 id,这里就可以用 extends 来继承

interface AddApiParamsModel {
  name: string;
  window: number;
}
interface EditApiParamsModel extends AddApiParamsModel {
  id: number;
}

同时继承多个:

interface AddApiParamsModel {
  name: string;
  window: number;
}
interface DeleteApiParamsModel {
  id: number;
}
//同时继承新增和删除的类型,生成编辑接口的参数类型
interface EditApiParamsModel extends AddApiParamsModel, DeleteApiParamsModel {}
泛型约束
interface Person {
  name: string;
  age: number;
}

function getUsersByAge<T extends Person>(entities: T[], user: T): T[] {
  return entities.filter((entity) => user.age === entity.age);
}

在调用 getUsersByAge 时传递的参数必须符合 Person 类型

interface SelectedDataModel<T extends string | number> {
  checkAll: boolean;
  selected: T[];
  unselected: T[];
}

这里泛型限制类型必须为 string 和 number

条件判断
type GetString<T> = T extends string ? T : never;

type StringKey = GetString<"name" | "age" | 1>;

//相当于:
type StringKey = "name" | "age";

keyof 索引类型查询

用于获取某个类型上的所有属性名,得到联合类型

interface Person {
  name: string;
  age: number;
}
let personProps: keyof Person; // 'name' | 'age'

项目中会用到表格排序功能,可以用 keyof 通过表格数据类型获取排序字段名

//表格数据
interface TableData {
  metricName: string;
  startTime: number;
  endTime: number;
}

interface FetchParamsData {
  sort: { sortKey: keyof TableData; order: "asc" | "desc" };
}
//相当于
interface FetchParamsData {
  sort: {
    sortKey: "metricName" | "startTime" | "endTime";
    order: "asc" | "desc";
  };
}

T[K] 索引访问

用于获取 T 类型上 K 属性的类型

let personName: Person["name"]; // string

使用第三方包的某些属性类型:

import type { FormProps } from "ant-design-vue";

const handleFinish: FormProps["onFinish"] = (values) => {
  console.log(values, formState);
};

in 映射类型

以相同的形式去转换旧类型里每个属性,产生新的类型

一般与 keyof 配合使用

interface Person {
  name: string;
  age: number;
}

type NewPerson = { [K in keyof Person]: string }; //{name: string; age: string}
  • k 为类型变量,它会依次绑定到每个属性
  • keyof Person 为需要迭代的属性名的集合(联合类型)

提取某些属性生成新的类型:

interface Person {
  name: string;
  age: number;
  score: number;
}

type NewPerson = { [K in keyof "name" | "score"]: Person[k] }; //{name: string; score: number}
重新映射

使用 as对映射类型中的键进行重新映射,来实现属性的过滤或转换

比如,把属性名都变成大写,则可以使用重新映射来实现

interface Person {
  name: string;
  age: number;
}

type NewPerson = { [K in keyof Person as Uppercase<K>]: Person[K] };
//相当于
type NewPerson = { NAME: string; AGE: number };

as后面的就是把索引转换成的目标结果

这里 Uppercase 是 TS 内置的方法,用于大写转换 于是 Person 的所有属性就通过重新映射都转换成了大写

项目中,给属性的获取定义对应的 getter 函数,比如:name => getName(),也可以使用重新映射实现

interface Person {
  name: string;
  age: number;
  score: number;
}

type NewPerson = {
  [K in keyof Person as `get${Capitalize<K>}`]: () => Person[K];
};
//相当于
type NewPerson = {
  getName: () => string;
  getAge: () => number;
  getScore: () => number;
};

原来的基础加上了 get,并且后面通过 TS 内置的类型 Capitalize 将内容首字母大写。

泛型工具

Partial

将类型的属性变成可选,注意这是浅 Partial

type Partial<T> = { [P in keyof T]?: T[P] };

可以通过递归实现简易的深度 Partial

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? deepPartial<T[P]> : T[P];
};
Required

将类型的属性变成必填

type Required<T> = { [P in keyof T]-?: T[P] };
Pick

从 T 中取出一系列 K 的属性

type Pick<T, K extends keyof T> = { [P in K]: T[P] };
interface Person {
  name: string;
  age: number;
}
type PersonName = Pick<Person, "name">; //{ name: string; }
Exclude

从 T 中找出 U 中没有的元素

type Exclude<T, U> = T extends U ? never : T;
interface Person {
  name: string;
  age: number;
  gender: string;
}
type PersonName = Exclude<"name" | "score", keyof Person>; //type PersonName = 'score'
Omit

从 T 中剔除某些属性

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
interface Person {
  name: string;
  age: number;
  gender: string;
}
type Pers onAge = Omit<Person, "name" | "gender">; //{ age: number; }

修改接口中的某个属性:

interface Person {
  name: string;
  age: number;
}

type NewPerson = Omit<Person, "name"> & {
  score: number;
};
//相当于
interface NewPerson {
  age: number;
  score: number;
}
Extract

从 T 中找出 U 中所有的元素

type Extract<T, U> = T extends U ? T : never;

剔除属性类型不为 string 的属性:

interface Person {
  name: string;
  age: number;
  1: string;
}

type StringParams = Pick<Person, Extract<keyof Person, string>>;

//相当于:
type StringParams = {
  name: string;
  age: number;
};

其中:

type PersonName = Extract<keyof Person, string>;
//相当于
type PersonName = "name" | "age";

提取属性值为 string 的属性:

interface Person {
  name: string;
  age: number;
  score: string;
}

type PersonValueType = {
  [key in keyof Person]: Person[key] extends string ? key : never;
};
// 相当于:
// interface PersonValueType = {
//   name: 'name';
//   age: never;
//   score: 'score';
// }
type PersonStringValueKey = PersonValueType[keyof Person];
// 相当于:
// "name" | "score" | never,其中never会被剔除
// type PersonStringValueKey = "name" | "score"
type StringValuePerson = Pick<Person, PersonStringValueKey>;
// 相当于:
// type StringValuePerson = {
//    name: string;
//    score: string;
// }