Reputation: 12193
Is it possible to map a union type to another union type in TypeScript?
What I'd Like to be able to do
e.g. Given a union type A:
type A = 'one' | 'two' | 'three';
I'd like to be able to map it to union type B:
type B = { type: 'one' } | { type: 'two'} | { type: 'three' };
What I have tried
type B = { type: A };
But this results in:
type B = { type: 'one' | 'two' | 'three' };
which is not quite what I want.
Upvotes: 47
Views: 24518
Reputation: 67310
I have found another solution that uses a utility type, but I'm not necessarily recommending it: I'm still learning typescript:
type A = 'one' | 'two' | 'three';
// type B = { type: 'one' } | { type: 'two'} | { type: 'three' };
type B = { type: Extract<A, any> }; // extract all from union
// ^?
const one: B = { type: 'one' };
const two: B = { type: 'two' };
const three: B = { type: 'three' };
const four: B = { type: 'four' }; // errors
FWIW, the definition of Extract
is type Extract<T, U> = T extends U ? T : never;
Upvotes: 1
Reputation: 51589
You can use conditional type for distributing over the members of the union type (conditional type always takes only one branch and is used only for its distributive property, I learned this method from this answer)
type A = 'one' | 'two' | 'three';
type Distribute<U> = U extends any ? {type: U} : never;
type B = Distribute<A>;
/*
type B = {
type: "one";
} | {
type: "two";
} | {
type: "three";
}
*/
Upvotes: 76