Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: is there a way to extends multiple interfaces and merge identical properties?

I have two interfaces A and B and they have one property in common

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

interface B {
  d: string;
}

interface C extends A,B {}

Ideally I want C to be

{
  a: boolean;
  b: number;
  c: string;
  d: boolean | string; <- merged
}

Is there a way to do that? I know I can use Pick to left out the identical key and then extends it but is there any other way to do it?

like image 204
Joji Avatar asked Sep 04 '20 05:09

Joji


Video Answer


2 Answers

Since A and B conflict, I believe you can't combine them. If you know what the conflicting keys are, you can omit them when declaring 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'
}
like image 100
xavdid Avatar answered Sep 30 '22 18:09

xavdid


Here you go:

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

Example usage:

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

like image 39
Mingwei Samuel Avatar answered Sep 30 '22 16:09

Mingwei Samuel