持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

前言

上篇文章 够用的TypeScript(1)|能用 Javascript 写的东西,终将会用 TypeScript 书写~ 留了一个关于 TS 实用类型的坑~现在来填了~
这八个Utility Types:实用类型以及实现 - 图1

大部分效果例子来自官网~


八种实用类型

官方的实用类型有很多~ 但我这里出于篇幅限制,这里只讲前八个比较常用的,以及他的实现~
至于实现的相关语法,会随着用到而进行说明~

Partial 可选

效果

将对象的所有属性值设置为可选——相加了 ?: 一样。

  1. interface Todo {
  2. title: string;
  3. description: string;
  4. }
  5. function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  6. return { ...todo, ...fieldsToUpdate };
  7. }
  8. const todo1 = {
  9. title: "organize desk",
  10. description: "clear clutter",
  11. };
  12. const todo2 = updateTodo(todo1, {
  13. description: "throw out trash",
  14. });

实现

可能是你没想到的简单

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

主要用到TS中的类型映射。将所有的属性都转为?:的,也就是可选的~

类型映射语法

类型映射,大概就是这样~

  1. { [ P in K ] : T }

这里的in有点像JS的for..in,也就是遍历 K 中所有属性,再用:映射回到合适的属性值

Required 必选

效果

把对象的所有属性都设置为必选

  1. interface Props {
  2. a?: number;
  3. b?: string;
  4. }
  5. const obj: Props = { a: 5 };
  6. const obj2: Required<Props> = { a: 5 };

最后一行代码就会报错~

Property ‘b’ is missing in type ‘{ a: number; }’ but required in type ‘Required‘.

实现

  1. type Required<T> = {
  2. [P in keyof T]-?: T[P];
  3. };

相当于就是通过添加减号-前缀将原来有的?去掉了,让这些属性不是可选的,自然就是必选的~

Readonly 只读

效果

对象或者数组所有属性设置为只读。

  1. interface Todo {
  2. title: string;
  3. }
  4. const todo: Readonly<Todo> = {
  5. title: "Delete inactive users",
  6. };
  7. todo.title = "Hello";

最后一行代码报错:

Cannot assign to ‘title’ because it is a read-only property.

实现

  1. type Readonly<T> = {
  2. readonly [P in keyof T]: T[P];
  3. };

是的,除了添加减号前缀,你还可以直接添加修饰符~
当然,其实直接添加修饰符也就是默认前面使用了加号+

Record 记录

效果

接收两个参数——keysvalues,使得对象中的keyvalue必须在keysvalues里面。

  1. interface CatInfo {
  2. age: number;
  3. breed: string;
  4. }
  5. type CatName = "miffy" | "boris" | "mordred";
  6. const cats: Record<CatName, CatInfo> = {
  7. miffy: { age: 10, breed: "Persian" },
  8. boris: { age: 5, breed: "Maine Coon" },
  9. mordred: { age: 16, breed: "British Shorthair" },
  10. };

实现

  1. type Record<K extends keyof any, T> = {
  2. [P in K]: T;
  3. };

keyof

keyof操作符是在 TypeScript 2.1 版本引入的,该操作符可以用于获取某种类型的所有键,其返回类型是联合类型。
这句K extends keyof any好像有点无厘头,让我们看看这个得到的到底是啥

  1. type KEY = keyof any //即 string | number | symbol

豁然开朗了,这个不就是说对象的keys类型可以取 stringnumbersymbol类型嘛~
比如这里的例子

  1. type CatName = "miffy" | "boris" | "mordred";

就是keys用了string这个类型,主要还是因为对象的键只能取这些类型,而这些键具体长什么样,就看传入的K
然后再映射到传入的T接口中~

Pick 选择

效果

从接口中选择一组属性值(通过key——属性值)

  1. interface Todo {
  2. title: string;
  3. description: string;
  4. completed: boolean;
  5. }
  6. type TodoPreview = Pick<Todo, "title" | "completed">; //从 Todo 接口中选
  7. const todo: TodoPreview = {
  8. title: "Clean room",
  9. completed: false,
  10. };
  11. todo;

实现

  1. type Pick<T, K extends keyof T> = {
  2. [P in K]: T[P];
  3. };

通过 第二个参数keyof T实现~

Omit 过滤

效果

通过key选择来过滤,差不多就是上一个的取反~

  1. interface Todo {
  2. title: string;
  3. description: string;
  4. completed: boolean;
  5. createdAt: number;
  6. }
  7. type TodoPreview = Omit<Todo, "description">;
  8. const todo: TodoPreview = {
  9. title: "Clean room",
  10. completed: false,
  11. createdAt: 1615544252770,
  12. };

实现

  1. type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

还真是 对 Pick 进行取反~要用到下面要说的 Exclude

简单理解Exclude就是数学集合中找出Type的“差集”,就是将类型A与B对比,返回A中独有的类型

Exclude 排除

效果

顾名思义,include包含的反义词,从一个类型(联合类型)中排除另一个类型。

  1. type T0 = Exclude<"a" | "b" | "c", "a">; //"b"|"c"

实现

前面的 Omit 实现用到这个,那么这个是怎么实现的呢

  1. type Exclude<T, U> = T extends U ? never : T;

?: 条件运算符

这里实际上就是一个?:条件运算符

好像很多语言都有这个东东呢,确实是非常好用~

判断 T 是否来自 U:

  • 啊,真来自 U 啊,不要了,给你个 never
  • 不是?自己人自己人,come on

    Extract 提炼

    效果

    从某个联合类型中,筛选出和另外一个联合类型相交的部分。

    1. type T0 = Extract<"a" | "b" | "c", "a" | "f">; //"a"

    实现

    1. type MyExtract<T,U> = T extends U ? T : never ;

    和上一个 Exclude很像哦
    判断是不是来自 U

  • 是,通过~

  • 不是,never!

    学习资源

  • Utility Types

    总结

    看完之后相信你对 TS 实用类型的效果、使用、实现都已经有所掌握了~

    思维导图总结

    这八个Utility Types:实用类型以及实现 - 图2

    文中措辞、知识点、格式如有疑问或建议,欢迎评论~你对我很重要~
    🌊如果有所帮助,欢迎点赞关注,一起进步⛵这对我很重要~