Ionic react: How to properly type (typescript) event object parameter in delegated anonymous onIonChange event handler

Viewed 1485

I'm using a form validation library (react-hook-form) in which I need to use a wrapper component (called Controller)for controlled inputs.

            <Controller
              render={({ onChange, onBlur, ...rest }) => (
                <IonCheckbox
                  {...rest} 
                  slot="start"
                  //@ts-ignore
                  onIonChange={(e) => onChange(e.target.checked)}
                  onIonBlur={onBlur}
                />
              )}
              control={control}
              rules={{
                required: { value: true, message: "this required" },
              }}
            />

Currently I have the compiler ignore the typing error because I've tried several things with no success:

1. What I thought would surely work:

onIonChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.checked)}

gives me a mouthful of an issue:

Type '(e: React.ChangeEvent) => void' is not assignable to type '(event: CustomEvent) => void'. Types of parameters 'e' and 'event' are incompatible. Type 'CustomEvent' is missing the following properties from type 'ChangeEvent': nativeEvent, isDefaultPrevented, isPropagationStopped, persistts(2322) components.d.ts(3680, 9): The expected type comes from property 'onIonChange' which is declared here on type 'IntrinsicAttributes & IonCheckbox & Pick<HTMLAttributes, "children" ...'

2. Based on the error message, I tried this:

onIonChange={(e: CustomEvent<CheckboxChangeEventDetail> => onChange(e.target.checked)}

Which give a much more concise error:

Cannot find name 'CheckboxChangeEventDetail'.ts(2304)

3. Grasping for straws with this one

onIonChange={(e: EventEmitter<CheckboxChangeEventDetail>) => onChange(e.target.checked)}

Which gives a couple of errors:

Type 'EventEmitter' is not generic.ts(2315) Cannot find name 'CheckboxChangeEventDetail'.

I've come up against this a couple times already and now have more @ts-ignore comments than i'm comfortable with. Anyone know how to properly type this with typescript?

1 Answers

You can just add the interface...

export interface CheckboxChangeEventDetail {
  value: any;
  checked: boolean;
}

and then set the code

<IonItem>
  <Controller
    render={({ onChange, onBlur }) => (
      <IonCheckbox
        onIonChange={(e: CustomEvent<CheckboxChangeEventDetail>) => {
          onChange(e?.detail.checked);
          console.log(e);
        }}
        onIonBlur={onBlur}
      />
    )}
    control={control}
    defaultValue={false}
    name="saveInfo"
    rules={{
      required: false,
    }}
  />
</IonItem>
Related