用最简单的话讲解Utility Types-Omit

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

背景

大家好,我是梅利奥猪猪!上次赖掉的omit这次肯定是逃不过了,请大家omit(omit直译就是忽略)下开头讲的这几句废话。其实上次讲解的Exclude就是为了这次做铺垫的,大家谅解下,听我娓娓道来!

正文

官方例子

先来看下官方的例子,以及说明

Constructs a type by picking all properties from Type and then removing Keys (string literal or union of string literals).

interface Todo {
  title: string;
  description: string;
  completed: boolean;
  createdAt: number;
}
 
type TodoPreview = Omit<Todo, "description">;
 
const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
  createdAt: 1615544252770,
};
 
todo;
 
type TodoInfo = Omit<Todo, "completed" | "createdAt">;
 
const todoInfo: TodoInfo = {
  title: "Pick up kids",
  description: "Kindergarten closes at 5pm",
};
 
todoInfo;

咳咳又是官方套路,老Todo选手了!todo选手拥有4个字段

  • 过了n天,我说不改原本的接口,把description字段去了,新接口只要剩下的字段
  • 又过了n天,我说不改原本的接口,我又要开始闹腾了,description我还是要的啊,completed和createdAt这2个我不要了,其他都要 Omit这个时候就登场解决了所有问题,我可以生成新的接口,你哪些字段不要告诉我就可以了,牛逼!知道Omit是干嘛用的,接下来我们实现下

分步实现

实现的原理,就是转换个角度思考,Omit不是剔除字段,保留剩下的字段嘛,那我们pick除了它不要的字段,其他字段都要不就可以了,先来搭架子

type MyOmit<T, K>

为什么是有T和K两个泛型(别打了别打了,竟然不给我说废话),这里注意下,K肯定是个string或者number或者symbol,所以我们可以进化下架子

type MyOmit<T, K extends keyof any>

然后我们的逻辑不是要改写成Pick嘛,所以肯定是要Pick原本接口的字段,再进化下

type MyOmit<T, K extends keyof any> = Pick<T, keyof T>

细心的小伙伴可能会发现,我们之前申明的K,即需要排除的字段都没有用到,所以上次我们说的Exclude就要登场了,我们Pick的字段,就是排除了K以外的字段,究极进化开始

type MyOmit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>

继续废话文学,中文直译,先看Exclude<keyof T, K>原本T里的字段,我写了需要排除的K字段,那剩下的就是我要的,接下去再使用Pick,不就是把我需要的字段,组装成我想要的新接口!完结撒花

源码讲解

直接上源码

/**
 * Construct a type with the properties of T except for those in type K.
 */
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

和我们写的一毛一样,XDM我们大家都是小天才哈哈,具体实现步骤大家有不清楚可以再对照分步实现看,这里就不赘述了,那么我们的Omit实现之旅到此结束了!

参考