Reputation: 3219
I have many interfaces like Foo
, Bar
, Baz
, ... and I need to have union of their mapped types where mapping is always the same (eg. with Pick
).
interface Foo {
a: 'FooA';
b: 'FooB';
}
interface Bar {
a: 'BarA';
b: 'BarB';
}
interface Baz {
a: 'BazA';
b: 'BazB';
}
I can do it "manually":
type A = Pick<Foo, 'a'> | Pick<Bar, 'a'> | Pick<Baz, 'a'>;
type B = Pick<Foo, 'b'> | Pick<Bar, 'b'> | Pick<Baz, 'b'>;
But I would like not to repeat myself. Following code doesn't do it as it unions the properties of types and maps it afterwards:
type Union = Foo | Bar | Baz;
type A = Pick<Union, 'a'>; // creates { a: 'FooA' | 'BarA' | 'BazA' } but I need { a: 'FooA' } | { a: 'BarA' } | { a: 'BazA' }
type B = Pick<Union, 'b'>;
Is there a way to do it?
Upvotes: 1
Views: 452
Reputation: 249536
You can use the distributing behavior of conditional types:
type PickDistributed<T, K extends keyof T> = T extends object ? Pick<T, K> : never;
type Union = Foo | Bar | Baz;
type A1 = PickDistributed<Union, 'a'>; // creates Pick<Foo, 'a'> | Pick<Bar, 'a'> | Pick<Baz, 'a'>
type B1 = PickDistributed<Union, 'b'>;
Upvotes: 2