从类型中排除属性

Qwe*_*tiy 111 typescript

我想从类型中排除一个属性.我怎样才能做到这一点?

比如我有

interface XYZ {
  x: number;
  y: number;
  z: number;
}
Run Code Online (Sandbox Code Playgroud)

我想排除属性z得到

type XY = { x: number, y: number };
Run Code Online (Sandbox Code Playgroud)

CRi*_*ice 254

适用于2.8或更高版本的TypeScript版本

在TypeScript 2.8中,Omit类型被添加到标准库中,这允许将省略类型简单地写为:

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

适用于2.8以下的TypeScript版本

您不能Exclude在2.8以下版本中使用该类型,但您可以为其创建替换,以便使用与上面相同的定义.但是,此替换只适用于字符串类型,因此它不如Exclude.

// Functionally the same as Exclude, but for strings only.
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T]
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>
Run Code Online (Sandbox Code Playgroud)

并且使用了该类型的示例:

interface Test {
    a: string;
    b: number;
    c: boolean;
}

// Omit a single property:
type OmitA = Omit<Test, "a">; // Equivalent to: {b: number, c: boolean}

// Or, to omit multiple properties:
type OmitAB = Omit<Test, "a"|"b">; // Equivalent to: {c: boolean}
Run Code Online (Sandbox Code Playgroud)

  • 是的 但这确实有一个缺点。例如,`Omit &lt;{a ?: string,b ?: boolean},“ b”&gt;`生成`{a:string | undefined},仍然会接受undefined作为值,但会丢失a上的可选修饰符。:( (4认同)
  • 请注意,对于TS 3.5,标准库的“忽略”定义与此处给出的定义不同。在stdlib中,它是`类型Omit &lt;T,K扩展了keyof any&gt; = Pick &lt;T,Exclude &lt;keyof T,K &gt;&gt;;`的变化虽然很小,却引起了一些争议[https:// github .com / microsoft / TypeScript / issues / 30825),因此请注意其中的区别。 (3认同)

for*_*d04 37

忽略

单一财产

type T1 = Omit<XYZ, "z"> // { x: number; y: number; }
Run Code Online (Sandbox Code Playgroud)

多重属性

type T2 = Omit<XYZ, "y" | "z"> // { x: number; } 
Run Code Online (Sandbox Code Playgroud)

有条件地属性

例如所有字符串类型:
type Keys_StringExcluded<T> = 
  { [K in keyof T]: T[K] extends string ? never : K }[keyof T]

type XYZ = { x: number; y: string; z: number; }
type T3a = Pick<XYZ, Keys_StringExcluded<XYZ>> // { x: number; z: number; }
Run Code Online (Sandbox Code Playgroud) 带有 TS 4.1键重映射/as映射类型 ( PR )子句的较短版本:
type T3b = { [K in keyof XYZ as XYZ[K] extends string ? never : K]: XYZ[K] } 
// { x: number; z: number; }
Run Code Online (Sandbox Code Playgroud)

string模式属性

例如排除 getter(带有 'get' 字符串前缀的道具)
type OmitGet<T> = {[K in keyof T as K extends `get${infer _}` ? never : K]: T[K]}

type XYZ2 = { getA: number; b: string; getC: boolean; }
type T4 = OmitGet<XYZ2> //  { b: string; }
Run Code Online (Sandbox Code Playgroud)

注意:TS 4.1 支持上述模板文字类型
注2:你也可以写 get${string}代替get${infer _}这里。


Pick,Omit和其他实用程序类型

如何使用 Typescript 选择和重命名某些键?(重命名而不是排除)

操场


Jas*_*ger 34

使用typescript 2.8,您可以使用新的内置Exclude类型.在2.8版本说明实际上在节"预定义条件类型"提到这一点:

注意:Exclude类型是此处建议的Diff类型的正确实现.[...]我们没有包含Omit类型,因为它被简单地写成Pick<T, Exclude<keyof T, K>>.

将此应用于您的示例,类型XY可以定义为:

type XY = Pick<XYZ, Exclude<keyof XYZ, "z">>
Run Code Online (Sandbox Code Playgroud)


Qwe*_*tiy 18

我找到了解决方案,声明了一些变量并使用spread运算符来推断类型:

interface XYZ {
  x: number;
  y: number;
  z: number;
}

declare var { z, ...xy }: XYZ;

type XY = typeof xy; // { x: number; y: number; }
Run Code Online (Sandbox Code Playgroud)

它有效,但我很高兴看到更好的解决方案.

  • 这是一个很棒的2.8之前的解决方案。typeof是Typescript较不被重视的功能之一。 (3认同)

Cor*_*han 8

打字稿 3.5+ 中

interface TypographyProps {
    variant: string
    fontSize: number
}

type TypographyPropsMinusVariant = Omit<TypographyProps, "variant">
Run Code Online (Sandbox Code Playgroud)


Krz*_*zor 7

If you prefer to use a library, use ts-essentials.

import { Omit } from "ts-essentials";

type ComplexObject = {
  simple: number;
  nested: {
    a: string;
    array: [{ bar: number }];
  };
};

type SimplifiedComplexObject = Omit<ComplexObject, "nested">;

// Result:
// {
//  simple: number
// }

// if you want to Omit multiple properties just use union type:
type SimplifiedComplexObject = Omit<ComplexObject, "nested" | "simple">;

// Result:
// { } (empty type)
Run Code Online (Sandbox Code Playgroud)

PS: You will find lots of other useful stuff there ;)


小智 5

打字稿 3.5

从 Typescript 3.5 开始,将包含 Omit 助手:TypeScript 3.5 RC - The Omit Helper Type

您可以直接使用它,并且在更新时应该删除您自己对 Omit 助手的定义。