I would like to have a method that takes action as first argument, and payload is decided based upon the the first argument.
Let's say I have a method as below:
async executeUpdateAction<K>(
action_type: K,
action_payload: TransferUpdateActions[K],
) {
if (action_type === TRANSFER_AVAILABLE_UPDATE_ACTIONS.CANCEL) {
return this.cancelTransfer(payload);
}
if (action_type === TRANSFER_AVAILABLE_UPDATE_ACTIONS.HOLD) {
return this.holdTransfer(payload);
}
...
}
This is simply an abstraction that invokes a function based on action type.
Each underlying method (i.e. cancelTransfer, holdTransfer) has its own unique payload requirement.
For instance, lets say holdTransfer requires the following parameters:
interface HoldPayload {
duration: string;
}
holdTransfer(payload: HoldPayload) {
...
}
This being the case, for method executeUpdateAction, if the first argument, action_type is equal to "hold", I want type auto completion so that payload is typed as HoldPayload.
Lastly, I have a wrapper that invokes executeUpdateAction, as below:
interface UpdateDto {
duration?: string, // payload argument required to execute "Hold"
admin_id?: number // payload argument required to execute "Cancel"
}
update(payload: UpdateDTO) {
this.executeUpdateAction(payload)
}
So as long as UpdateDTO payload matches ONE of Cancel or Hold Payload, it should be type-safe.
Please advise.
CodePudding user response:
Try this:
type Action = "cancel" | "hold";
type Payload = {
cancel: {
userId: string;
};
hold: {
userId: string;
duration: number;
amount: number;
};
};
function executeAction<T extends Action>(action: T, payload: Payload[T]) {
return;
}
Seems like Typescript doesn't seem to be able to narrow down generics for the second param. In this case you can safely cast your payload.
function executeAction<T extends Action>(action: T, payload: Payload[T]) {
if (action === "cancel") {
cancelTransfer(payload as Payload["cancel"]);
}
}