Home > Mobile >  Make one value in enum required but only one
Make one value in enum required but only one

Time:12-22

I have something that looks like this.

export enum TableCellType {
    Index = 'index',
    Text = 'text',
    Template = 'template',
}

export interface TableCell {
    class?: string;
}

I want the TableCell interface to make one of the values in the enum required, but if one is on the object, then disallow others.

Example:

let a = {index: 2, text: 'hello'}

This is not OK because two of the values from the enum is on the object. Only one can exist at any given time.

let b = {text: 'This works'}

This is ok since there are not multiple from the enum.

How do I go about typehinting this so that typescript understands?

Thanks.

CodePudding user response:

You can get it working for object literals (in addition, I specified the type for properties defined by TableCellType):

export enum TableCellType {
    Index = 'index',
    Text = 'text',
    Template = 'template',
}

type OneOfTableCellTypes = {index: number; text?: never; template?: never} 
  | {index?: never; text: string; template?: never}
  | {index?: never; text?: never; template: string}

export type TableCell = OneOfTableCellTypes & {
    class?: string;
}

let a: TableCell = {index: 2, text: 'hello'} // ERROR
let b: TableCell = {index: 2}                // OK

Playground

If you have more variants, you can go with:

type TableCellTypeMap = {
    index: number;
    text: string;
    template: string,
}

type ExcludeAllExcept<T, K extends keyof T> = {[Prop in keyof T]?: Prop extends K ? T[Prop]: never}
type oneOf<T> = { [K in keyof T]: Pick<T, K> & ExcludeAllExcept<T, K>}[keyof T];

export type TableCell = oneOf<TableCellTypeMap> & {
    class?: string;
}

let a: TableCell = {index: 2, text: 'hello'} // ERROR
let b: TableCell = {index: 2}                // OK

Playground with oneOf

Unfortunately, this wont prevent you from assigning an incorrect object (having 2 properties) in runtime.

  • Related