Home > Software engineering >  Define custom types and achieve polymorphic behaviour
Define custom types and achieve polymorphic behaviour

Time:03-10

I have two types of objects save and exit and another one save-exit which acts like both. The purpose is when I run the exec function below in the case of the save-exit object type both if blocks will be covered:

const save = Symbol('save');
const exit = Symbol('exit');

type Save = typeof save;
type Exit = typeof exit;
type SaveExit = Save & Exit;
type MenuRequestType = Save | Exit | SaveExit;

function exec(val: MenuRequestType) {
    if (val === save) {
        console.log('save')
    }
    if (val === exit) {
        console.log('exit')
    }
}

let a: MenuRequestType = /* new SaveExit(); */
exec(a) // prints both save and exit

I also tried to do this with enums but no progress so far. Any ideas how to adjust this so it works?

CodePudding user response:

Update in response to your comment:

TS Playground

const save = Symbol('save');
const exit = Symbol('exit');
const saveExit = Symbol('save-exit');

// You might not need these:
// type Save = typeof save;
// type Exit = typeof exit;
// type SaveExit = typeof saveExit;

const allActions = [save, exit, saveExit] as const; // readonly [typeof save, typeof exit, typeof saveExit]
type Action = typeof allActions[number]; // typeof save | typeof exit | typeof saveExit

const actionFunction: Record<Action, () => void> = {
  [save] () {
    console.log('save');
  },
  [exit] () {
    console.log('exit');
  },
  [saveExit] () {
    this[save]();
    this[exit]();
  },
};

function act (action: Action): void {
  actionFunction[action]();
}

act(save) // "save"
act(exit) // "exit"
act(saveExit) // "save", "exit"

Original answer:

Just create a third type to represent both:

TS Playground

const save = Symbol('save');
const exit = Symbol('exit');
const saveExit = Symbol('save-exit');

// You might not need these:
// type Save = typeof save;
// type Exit = typeof exit;
// type SaveExit = typeof saveExit;

const allActions = [save, exit, saveExit] as const; // readonly [typeof save, typeof exit, typeof saveExit]
type Action = typeof allActions[number]; // typeof save | typeof exit | typeof saveExit

function act (action: Action): void {
  switch (action) {
    case save: {
      console.log('save');
      break;
    }
    case exit: {
      console.log('exit');
      break;
    }
    case saveExit: {
      console.log('save');
      console.log('exit');
      break;
    }
  }
}

act(save) // "save"
act(exit) // "exit"
act(saveExit) // "save", "exit"

CodePudding user response:

Though not a perfect solution I'm actually looking for something like this:

const save = Symbol('save');
const exit = Symbol('exit');

const Save = { [save]: true };
const Exit = { [exit]: true };
const SaveExit = { [save]: true, [exit]: true };
type ActionType = typeof Save | typeof Exit | typeof SaveExit;

function exec(val: ActionType) {
    if (save in val) {
        console.log('save')
    }
    if (exit in val) {
        console.log('exit')
    }
}

let a: ActionType = SaveExit;
exec(a) // prints both save and exit

any other more elegant solutions/improvements are highly welcome!

  • Related