bingles
bingles

Reputation: 12193

TypeScript: Map union type to another union type

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

Answers (2)

Daniel Kaplan
Daniel Kaplan

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

artem
artem

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

Related Questions