I don't have the right typescript vocabulary to describe what i am trying to achieve, so i will be using my code snippet to describe what i am aiming at. I have two interfaces ActionPayloadTypes
and Action
interface ActionPayloadTypes {
FETCH_LIST_REQUEST: any,
FETCH_LIST_SUCCESS: string[],
FETCH_LIST_FAILURE: string
}
interface Action <T extends keyof ActionPayloadTypes> {
type: T
payload: ActionPayloadTypes[T]
}
and I'm wanting to create a union type of Actions based on these 2 interfaces.
Basically i want
type Actions = Action<'FETCH_LIST_REQUEST'> | Action<'FETCH_LIST_SUCCESS'> | Action<'FETCH_LIST_FAILURE'>
without having to write the union types manually for each key. I tried using <keyof ActionPayloadTypes>
it creates a union type in the Action
. See below.
Action<'FETCH_LIST_REQUEST' | 'FETCH_LIST_SUCCESS' | 'FETCH_LIST_FAILURE'>
What am i doing wrong here?
CodePudding user response:
type Actions = {
[A in keyof ActionPayloadTypes]: Action<A>
}[keyof ActionPayloadTypes];
You have to map each key of the ActionPayloadTypes
type into a "call" to the Action
type. Then you index this partial result with the keys of ActionPayloadTypes
to get the desired union.
CodePudding user response:
You're on the right path. As you noted Action<keyof ActionPayloadTypes>
gives you a type where the generic parameter is the union of keys.
In order to get a union with each type of Action
I break it into two steps:
First I use a mapped type to get a map with values for each type of Action
type ActionMap = { [K in keyof ActionPayloadTypes]: Action<K> }
// {
// FETCH_LIST_REQUEST: Action<"FETCH_LIST_REQUEST">;
// FETCH_LIST_SUCCESS: Action<"FETCH_LIST_SUCCESS">;
// FETCH_LIST_FAILURE: Action<"FETCH_LIST_FAILURE">;
// }
From here, I can create a union type based on the values in this map
type ActionUnion = ActionMap[keyof ActionMap];
// Action<"FETCH_LIST_REQUEST"> | Action<"FETCH_LIST_SUCCESS"> |
// Action<"FETCH_LIST_FAILURE">
Of course, you can combine these into a single type to be more succinct
type ActionUnion = {
[K in keyof ActionPayloadTypes]: Action<K>
}[keyof ActionPayloadTypes];
// Action<"FETCH_LIST_REQUEST"> | Action<"FETCH_LIST_SUCCESS"> |
// Action<"FETCH_LIST_FAILURE">