TypeScript:有没有一种方法可以扩展多个接口并合并相同的属性?

9

我有两个接口AB,它们有一个属性是共同的。

interface A {
  a: boolean;
  b: number;
  c: string;
  d: boolean;
}

interface B {
  d: string;
}

interface C extends A,B {}

理想情况下,我希望C 是...
{
  a: boolean;
  b: number;
  c: string;
  d: boolean | string; <- merged
}

有没有其他方法可以做到这一点?我知道我可以使用Pick来留下不同的键然后扩展它,但还有其他方法吗?


请查看 https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#intersection-types。 - Berk Kurkcuoglu
3个回答

4

由于AB存在冲突,我认为你不能将它们结合起来。如果你知道哪些键冲突,你可以在声明C时省略它们:

interface A {
  a: boolean;
  b: number;
  c: string;
  d: boolean;
}

interface B {
  d: string;
}

interface C extends Omit<A, 'd'>, Omit<B, 'd'> {
  d: string | boolean
}

let c: C = {
  a: true, b: 3, c: 'a', d: 'a'
}

4

好的,这里是您需要的翻译:

type Merge<X, Y> = {
    [K in (keyof X | keyof Y)]:
        (K extends keyof X ? X[K] : never)
        | (K extends keyof Y ? Y[K] : never)
};

使用示例:

interface A {
  a: boolean;
  b: number;
  c: string;
  d: boolean;
}

interface B {
  d: string;
}

type C = Merge<A, B>;
// Result:
type C = {
    a: boolean;
    b: number;
    c: string;
    d: string | boolean;
}
Playground Link是一个TypeScript在线编辑器和调试工具。你可以在这里输入TS代码并立即查看结果。此外,Playground Link还提供了许多示例代码和功能,如自动完成、错误检查和导入库等。无需安装任何软件或配置环境即可开始使用!

2

这是可能的,我会尽力解释我的回答中的每个部分。

/** Returns keys in the left type which are not in the right type. */
type UniqueLeftKeys<T, U> = Exclude<keyof T, keyof U>
/** Returns keys in the right type which are not in the left type. */
type UniqueRightKeys<T, U> = Exclude<keyof U, keyof T>
/** Returns keys that exist in BOTH the left and right types. */
type CommonKeys<T, U> = keyof T & keyof U
type Merge<T, U> = {
  [k in UniqueLeftKeys<T, U>]: T[k] // First part
} & {
    [k in UniqueRightKeys<T, U>]: U[k] // Second part
  } & {
    [k in CommonKeys<T, U>]: T[k] | U[k] // Third part
  }

秘密在于Merge类型,它由三部分组成。
第一部分将仅在LEFT类型中而不在RIGHT类型中的键添加到结果中。在您的示例中,属性a, b, c仅在接口A中,因此我们将这三个属性添加到我们的结果类型中。
第二部分获取仅在RIGHT类型中而不在LEFT类型中的键,并将这些属性添加到结果中。在您的示例中,右侧类型B不包含任何不在A中的键,因此我们不会将任何内容添加到结果类型中。
第三部分获取两种类型中都有的键,然后将这些键添加到结果类型中,其中这些键的类型是两种类型的联合。
现在您可以像这样使用此代码:
type C = Merge<A, B>
const c: C = {
  a: false,
  b: 1,
  c: 'abc',
  d: false // NOTE: we can also use string here
}

你可以轻松地通过内联这些额外的类型定义(UniqueLeftKeys、UniqueRightKeys和CommonKeys)来简化此代码,但是我在示例中保留了它们,因为这有助于解释每个步骤发生了什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接