0

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.

1
  • Make sure you look at the tag's details. Typescript-typings is a very specific thing that is not related to your question at all. Commented Sep 15, 2021 at 16:38

1 Answer 1

1

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"]);
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

if (action_type === TRANSFER_AVAILABLE_UPDATE_ACTIONS.hold) { return this.holdTransfer(payload); } hold(payload: TransferUpdatePayload['hold']) i get following error: Argument of type '{ amount: number; } | { type: DocumentResubmissionType[]; } | { partner_id: number; } | undefined' is not assignable to parameter of type '{ amount: number; }'. Type 'undefined' is not assignable to type '{ amount: number; }'
Updated my answer. You can try to cast it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.