Optional properties on TypeScript union OR types

Viewed 125

EDIT: Added full example

I'm trying to more strictly define an object type with optional properties for React props using TypeScript (original answer I used here - Typescript interface optional properties depending on other property):

export enum IXDirection {
    Right  = "right"
  , Center = "center"
  , Left   = "left"
};

export interface IFieldOption {
    label: string
  , value: string | number
};

export enum TFilterType {
    Date         = "date"
  , Input        = "input"
  , Select       = "select"
  , AutoComplete = "autocomplete"
}

type IDataTableColumnGeneric = {
    heading : string | null
  , width?  : string
  , align?  : IXDirection
  , onOrder?: (value: "asc" | "desc") => void
};

type TDataTableColumnFilter = {
    filterType?   : TFilterType.Date | TFilterType.Input
  , filterOptions?: never
  , onInputChange?: never
} | {
    filterType    : TFilterType.Select
  , filterOptions : IFieldOption[]
  , onInputChange?: never
} | {
    filterType    : TFilterType.AutoComplete
  , filterOptions?: IFieldOption[]
  , onInputChange : (value: string) => void
};

export type IDataTableColumn = IDataTableColumnGeneric & TDataTableColumnFilter;

With the above, I hope to ensure that certain filter types include certain properties while others should not. In using a simple example to test this:

const data = {
        heading   : "Date"
      , filterType: TFilterType.Date
      , width     : "100px"
      , onOrder   : (value: "asc" | "desc") => {}
};

function test(data: IDataTableColumn) {
  console.log(data);
}

test(data);

The above example should use heading in IDataTableColumnGeneric and the first type in IDataTableColumnFilter in using filterType as TFilterType.Date which essentially should mean that filterOptions and onInputChange must be undefined or not passed. There is a longer error here related to other parts using the same type but the major issue I've picked up:

Property 'onInputChange' is missing in type '{ heading: string; filterType: TFilterType; width: string; onOrder: (value: "asc" | "desc") => void; }' but required in type '{ filterType: TFilterType.AutoComplete; filterOptions?: IFieldOption[] | undefined; onInputChange: ((value: string) => void) | undefined; }'.

I've tried using strings in place of the enum but it gives a similar error relating to strings of course. Is there a way to achieve this?

EDIT: Simplified example

0 Answers
Related