TypeScript:从类型/减法类型中删除键

Lei*_*cki 14 generics decorator typescript reactjs higher-order-components

我想定义一个泛型类型ExcludeCart<T>,它基本上是T用给定键(在我的情况下cart)删除的.所以,例如,ExcludeCart<{foo: number, bar: string, cart: number}>将是{foo: number, bar: string}.有没有办法在TypeScript中执行此操作?

这就是我想要这样做的原因,以防我咆哮错误的树:我正在将现有的JavaScript代码库转换为TypeScript,它包含一个名为的装饰器函数cartify,它接受一个React组件类Inner并返回另一个组件类Wrapper.

Inner应该采取cart道具,以及零或多个其他道具.Wrapper接受一个cartClient道具(用于生成cart要传递到的道具Inner)和任何Inner接受的道具,除了 cart.

换句话说,一旦我弄清楚如何定义ExcludeCart,我想用它来做:

function cartify<P extends {cart: any}>(Inner: ComponentClass<P>) : ComponentClass<ExcludeCart<P> & {cartClient: any}>
Run Code Online (Sandbox Code Playgroud)

alt*_*gel 41

自从TypeScript 2.8和引入以来Exclude,现在可以写如下:

type Without<T, K> = {
    [L in Exclude<keyof T, K>]: T[L]
};
Run Code Online (Sandbox Code Playgroud)

或者,更简洁,更简洁:

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

对于您的使用,您现在可以编写以下内容:

type ExcludeCart<T> = Without<T, "cart">;
Run Code Online (Sandbox Code Playgroud)

  • 文档还提到`类型Omit <T,K> = Pick <T,Exclude <keyof T,K >>`也可以,[在2.8发行说明中](https://www.typescriptlang.org/docs /handbook/release-notes/typescript-2-8.html#predefined-conditional-types)(在链接部分的底部).这个版本的`Omit`似乎与预期的可选成员一样工作. (6认同)

Mat*_*ias 30

虽然这已经得到正确回答,但我想指出TypeScript 3.5确实添加了一个Omit<T, E>类型。

type NoCart = Omit<{foo: string, bar: string, cart: number}, "cart">;
Run Code Online (Sandbox Code Playgroud)

这导致{foo: string, bar: string}类型。

  • 要省略多个,请执行 `type NoCart = Omit&lt;{foo: string, bar: string, cart: number}, "cart" | “酒吧”&gt;;` (6认同)

Adr*_*ard 8

虽然没有内置的减法类型,但您现在可以将其破解为:

type Sub0<
    O extends string,
    D extends string,
> = {[K in O]: (Record<D, never> & Record<string, K>)[K]}

type Sub<
    O extends string,
    D extends string,
    // issue 16018
    Foo extends Sub0<O, D> = Sub0<O, D>
> = Foo[O]

type Omit<
    O,
    D extends string,
    // issue 16018
    Foo extends Sub0<keyof O, D> = Sub0<keyof O, D>
> = Pick<O, Foo[keyof O]>
Run Code Online (Sandbox Code Playgroud)

在问题的情况下,你会这样做:

type ExcludeCart<T> = Omit<T, 'cart'>
Run Code Online (Sandbox Code Playgroud)

使用TypeScript> = 2.6,您可以将其简化为:

/**
 * for literal unions
 * @example Sub<'Y' | 'X', 'X'> // === 'Y'
 */
export type Sub<
    O extends string,
    D extends string
    > = {[K in O]: (Record<D, never> & Record<string, K>)[K]}[O]

/**
 * Remove the keys represented by the string union type D from the object type O.
 *
 * @example Omit<{a: number, b: string}, 'a'> // === {b: string}
 * @example Omit<{a: number, b: string}, keyof {a: number}> // === {b: string}
 */
export type Omit<O, D extends string> = Pick<O, Sub<keyof O, D>>
Run Code Online (Sandbox Code Playgroud)

在操场上测试它