Home > Mobile >  How to access properties from same option of union in typescript?
How to access properties from same option of union in typescript?

Time:05-27

I have the following example code:

type actionT =
  | {
      name: "action1";
      method: (params: { x: number }) => void;
      params: { x: number };
    }
  | {
      name: "action2";
      method: (params: { y: string }) => void;
      params: { y: string };
    };

const x: actionT = {
  name: "action1",
  method: (params) => {
    console.log("Got", params.x);
  },
  params: { x: 12 },
};

const y: actionT = {
  name: "action2",
  method: (params) => {
    console.log("Got", params.y);
  },
  params: { y: "hi" },
};

const run_action_1 = (action: actionT) => {
  switch (action.name) {
    case "action1": {
      action.method(action.params);
      break;
    }
    case "action2": {
      action.method(action.params);
      break;
    }
  }
};

const run_action_2 = (action: actionT) => {
  action.method(action.params); // Typescript Error
};

run_action_1(x); // Works
run_action_1(y); // Works
run_action_2(x); // Does not work
run_action_2(x); // Does not work

I understand why it does not work. However, I am looking for a way to make it work other than wrapping it in a switch case with identical function call. That is because in my actual code I have a lot of actions.

The error I am seeing is:

Argument of type '{ x: number; } | { y: string; }' is not assignable to parameter of type '{ x: number; } & { y: string; }'.
  Type '{ x: number; }' is not assignable to type '{ x: number; } & { y: string; }'.
    Property 'y' is missing in type '{ x: number; }' but required in type '{ y: string; }'.

CodePudding user response:

Wouldn't a generic suit your needs ?

type actionT<T = any> = {
  name: "action";
  method: (params: T) => void;
  params: T;
}

const x: actionT<{ x: number }> = {
  name: "action",
  method: (params) => {
    console.log("Got", params.x);
  },
  params: { x: 12 },
};

const y: actionT<{ y: string }> = {
  name: "action",
  method: (params) => {
    console.log("Got", params.y);
  },
  params: { y: "hi" },
};

const run_action_2 = (action: actionT) => {
  action.method(action.params); 
};

run_action_2(x); 
run_action_2(x); 

Playground

  • Related