0

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, and later in the code, do a type guard and get the proper type for the dropdown change event.

3
  • It looks like you are trying to compute the onInputChange type at runtime, which is not possible with TypeScript. Commented May 13, 2021 at 13:12
  • no, I'am not. I'm doing a typeguard in my code. I expect the type to be DropDownChangeEventHandler | FormChangeEventHandler Commented May 13, 2021 at 13:18
  • Why not declare it as such? You could potentially use a discriminated union to get compile type checking, but IInput['type'] extends inputTypes.dropdown is a compile-time check that will only run once. Commented May 13, 2021 at 13:27

1 Answer 1

0

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' 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']>;    
}
Sign up to request clarification or add additional context in comments.

1 Comment

Like your solution, I'll try it in a minute

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.