Reputation: 179
I would like to create an object where the property name is a value from a union type, and the type of the value based on that prop type, e.g:
type Direction =
"horizontal"
| "vertical"
| "diagonal"
;
// Choose one of this types based on Direction option
interface HorizontalData { foo: number; }
interface VerticalData { bar: string; }
interface DiagonalData { baz: boolean; }
type Result<D extends Direction> = {
data: << type based on D value >>;
};
Upvotes: 1
Views: 293
Reputation: 327774
Yes, this is possible. You can define a type which represents the mapping from each property name to the corresponding ***Data
, like this:
type DirectionMapping = {
"horizontal": HorizontalData
"vertical": VerticalData
"diagonal": DiagonalData
};
(Aside: If you want you can remove your original definition of Direction
and replace it with:
type Direction = keyof DirectionMapping;
which amounts to the same thing, but keeps your code DRY.)
Note that you will never need an instance of DirectionMapping
at runtime. Instead you use it to look up the output type in the definition of Result
:
type Result<D extends Direction> = {
data: DirectionMapping[D]; // uses indexed-access/lookup type
};
And test that it behaves as expected:
const horz: Result<"horizontal"> = { data: { foo: 3 } }; // okay
const vert: Result<"vertical"> = { data: { foo: 3 } }; // error
Hope that helps. Good luck!
Upvotes: 2