【问题标题】:Typescript: Omit a property from all interfaces in a union, but keep the union structure打字稿:从联合中的所有接口中省略一个属性,但保留联合结构
【发布时间】:2019-07-18 23:35:21
【问题描述】:

我是 typescript 的新手,我有几个这样定义的接口:

interface A {
  toRemove: string;
  key1: "this1";
  key2: number;
}
interface B {
  toRemove: string;
  key1: "this2";
  key3: string;
}

两个接口的联合:

type C = A|B;

我想做的是通过C从两个接口中删除toRemove键,如下所示:

type CC = Omit<A, "toRemove">|Omit<B, "toRemove">;

但不必从两个接口中省略密钥。 这将是理想的:

type CC = Omit<C, "toRemove">;

但是,不幸的是,CC 将是 Pick&lt;A|B, "key1"&gt; 类型,其中 key1 是两个接口中都存在的键。

本质上,我要实现的是一种要转换的“功能”:

A1|A2|...|An

进入:

Omit<A1, K keyof A1>|Omit<A1, K keyof A2>|...|Omit<An, K keyof An>

我遇到了这个答案https://stackoverflow.com/a/56297816/6520174,我觉得我需要的部分内容就在其中,但我并不真正理解该代码中发生了什么。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您希望在联合中分发Omit。幸运的是,您可以使用distributive conditional types 来实现:

    type DistributiveOmit<T, K extends keyof any> = T extends any
      ? Omit<T, K>
      : never;
    

    T extends any 构造看起来并没有多大作用,但由于T 是一个类型参数,它会将条件类型分配给T 的任何联合组成部分。

    让我们测试一下:

    type CC = DistributiveOmit<C, "toRemove">;
    // type CC = Pick<A, "key1" | "key2"> | Pick<B, "key1" | "key3">
    

    您可以验证这是否等同于您想要的 CC 类型。

    希望有所帮助;祝你好运!

    Link to code

    【讨论】:

    • 我已将编辑器设置为警告我使用任何类型,我相信在这种情况下可以将其删除。 K extends keyof any可以换成K extends keyof T,不能T extends any换成T extends T,因为会解析成A extends T?... | B extends T?...
    • 您可以根据需要将keyof any 替换为PropertyKey;用keyof T 替换它可能会满足您的用例,但standard library's definition of Omit 使用keyof any,所以这就是我使用它的原因。至于T extends any,您可能可以用T extends T 替换它,但我没有使用过那个构造。我怀疑它会被解析为A extends A ? ... | B extends B ? ...。我的直觉是改用T extends unknown
    • PropertyKeyT extends unknown 是完美的!即使标准库使用keyof any,我也会使用它来从类型/接口中删除属性,所以PropertyKey 就足够了。我将阅读更多关于使用unknown 的含义。感谢所有的帮助。
    【解决方案2】:

    另一种方法是:

    export declare type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
    
    type CC = Without<A, "toRemove">| Without<B, "toRemove">;
    

    【讨论】:

    • 谢谢,但这不行,你的Without 基本上是Typescript 的Omit。我也在问题中说:without having to omit the key from both interfaces。显然,您的解决方案需要从两个界面中删除密钥。
    猜你喜欢
    • 1970-01-01
    • 2019-12-02
    • 2022-01-04
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    相关资源
    最近更新 更多