0

So I really don't know if this is possible but I wanted to ask anyway. So I have a class named Row

export class Row {
    buttons: MenuOption[] | ButtonOption[];
    rowType: RowTypes;
    constructor(buttons: MenuOption[] | ButtonOption[], rowType: RowTypes) {
        this.buttons = buttons;
        this.rowType = rowType;
    }

}

And it has a property called rowType which is basically an enum

export enum RowTypes {
    SelectMenu = 0,
    ButtonMenu = 1
}

It also has a property called buttons and It can be either a MenuOption array, or a ButtonOption array. Now here's the problem. Can I tell typescript to change the type of the property buttons based on the rowType value? So for example if the rowType value is 1 then the buttons type is MenuOption.

kalempster
  • 397
  • 3
  • 13

2 Answers2

1

You can use constructor overloads so that you can ensure a 1:1 correspondence between RowTypes and the type of the buttons argument:

export class Row {
    buttons: MenuOption[] | ButtonOption[];
    rowType: RowTypes;
    
    constructor(buttons: MenuOption[], rowType: RowTypes.SelectMenu)
    constructor(buttons: ButtonOption[], rowType: RowTypes.ButtonMenu)
    constructor(buttons: MenuOption[] | ButtonOption[], rowType: RowTypes) {
        this.buttons = buttons;
        this.rowType = rowType;
    }
}

See proof-of-concept on TypeScript Playground.

Terry
  • 63,248
  • 15
  • 96
  • 118
0

You can type constructor arguments to make code a bit cleaner, e.g.

type RowCtor = {
  buttons: MenuOption[];
  rowType: RowTypes.SelectMenu;
} | {
  buttons: ButtonOption[];
  rowType: RowTypes.ButtonMenu;
}

export class Row {
    buttons: MenuOption[] | ButtonOption[];
    rowType: RowTypes;
    constructor(args: RowCtor) {
        this.buttons = args.buttons;
        this.rowType = args.rowType
    }
}
ABOS
  • 3,723
  • 3
  • 17
  • 23