仅黑白差异排除和省略(选择和排除)打字稿

kus*_*lvm 27 typescript

根据Pick @ typescriptlang.org的定义,它仅为提到的属性构造一个新类型。Exclude @ typescriptlang.org与它相反。

我见过以下用法

export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
Run Code Online (Sandbox Code Playgroud)

但我不太明白。我们本可以简单Exclude地忽略非必填字段并构建一种新类型的字段。为什么组合PickExclude用作Omit

另一个例子:

function removeName<Props extends ExtractName>(
  props: Props
): Pick<Props, Exclude<keyof Props, keyof ExtractName>> {
  const { name, ...rest } = props;
  // do something with name...
  return rest;
}
Run Code Online (Sandbox Code Playgroud)

上面的返回类型不能用Excludeas重写Exclude<Props, ExtractName>吗?

Tit*_*mir 46

你是对的Pick,它需要一个对象类型并提取指定的属性。所以:

 Pick<{ a: string, b:string }, 'a' > === { a: string } 
Run Code Online (Sandbox Code Playgroud)

与此相反的其实是后来添加的Omit。此类型采用对象类型并从该类型中删除指定的属性。

 Omit<{ a: string, b:string }, 'a' > === { b: string }
Run Code Online (Sandbox Code Playgroud)

Exclude 是一种不同的野兽,它采用联合类型并删除该联合的组成部分。

Exclude<string | number, string > === number
Run Code Online (Sandbox Code Playgroud)

Exclude 定义为:

type Exclude<T, U> = T extends U ? never : T;
Run Code Online (Sandbox Code Playgroud)

这意味着,Exclude将返回never如果T延伸U,并且T如果它不。所以这意味着:

  • Exclude<string, number>string
  • Exclude<string, string>never

问题是条件类型分布在裸类型参数上。所以这意味着如果应用于联合,我们会得到以下结果:

Exclude<string | number, number>
    => Exclude<string, number> | Exclude<number, number> // Exclude distributes over string | number
    => string | never => // each application of Exclude resolved to either T or never
    => string  // never in unions melts away
Run Code Online (Sandbox Code Playgroud)

Exclude用于 的定义OmitExclude<keyof T, K>采用 的键的联合T并删除由 指定的键K。然后Pick从中提取剩余的属性T

编辑

虽然两者OmitExclude采取两种类型的参数(没有关系,两者之间的执行),他们不能交替使用。看看这些类型的一些应用程序的结果:

type T0 = Omit<{ a: string, b: string }, "a"> //  { b: string; }, a is removed 
type T1 = Exclude<{ a: string, b: string }, "a"> // { a: string, b: string }, a does not extend { a: string, b: string } so Exclude does nothing 

type T2 = Omit<string | number, string> // Attempts to remove all string keys (basically all keys) from string | number , we get {}
type T3 = Exclude<string | number, string> // string extends string so is removed from the union so we get number
Run Code Online (Sandbox Code Playgroud)