简体   繁体   中英

typescript conditional type on enum key

I though this was very straightforward bu apparently I was wrong. How can I create a simple conditional type based on an enum key? like this:

export enum inputTypes {
  text = 'text',
  email = 'email',
  password = 'password',
  number = 'number',
  date = 'date',
  textarea = 'textarea',
  dropdown = 'dropdown',
  checkbox = 'checkbox',
}

export interface IInput {
  id: string,
  type: inputTypes,
  name: string,
}

And the conditional type based on the inputType:

export type onInputChange =
IInput['type'] extends inputTypes.dropdown
? DropDownChangeEventHandler
: FormChangeEventHandler;

I've tried some variations with keyof typeof keyof typeof And could not reach what I am trying.

The end result that I need is that if the input type is dropdown I'd like to have a different change event. So my type onInputChange would be equal to: DropDownChangeEventHandler | FormChangeEventHandler DropDownChangeEventHandler | FormChangeEventHandler , and later in the code, do a type guard and get the proper type for the dropdown change event.

I'm not sure I correctly understood what you're trying to do, but I think the issue might be with your condition on onInputChange type:

export type onInputChange =
   IInput['type'] extends inputTypes.dropdown
   ? DropDownChangeEventHandler
   : FormChangeEventHandler;

What you're saying here is: if the type of property type on IInput interface extends 'dropdown' give me type DropDownChangeEventHandler else give me type FormChangeEventHandler .

The point is that condition will never be true, as you defined type on IInput as inputTypes . Enum types define a union of each enum member and 'foo' | 'bar' extends 'foo' 'foo' | 'bar' extends 'foo' will always be false.

I guess, what you actually want to check in your condition is not the type of type property on IInput interface, but the type of type property on a specific implementation of that interface. Obviously that information is only available once you implemented the interface.

A way to do this is probably using generics:

export type onInputChange<T> =
    T extends inputTypes.dropdown
    ? DropDownChangeEventHandler
    : FormChangeEventHandler;

export class Test implements IInput {
    id: string;
    type: inputTypes.dropdown;
    name: string;
    onChange: onInputChange<Test['type']>;    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM