Custom event types in Ionic

February 11th 2022 Ionic 4+ Angular TypeScript

In Ionic 6, component events have well-documented, strongly typed arguments. This should allow them to be used in such event handlers:

onInputChange(inputEvent: InputCustomEvent) {
  console.log(inputEvent.detail.value);
}

Provided, of course, you have the following markup in the template:

<ion-input (ionChange)="onInputChange($event)"></ion-input>

Unfortunately, the outputs in Angular are still typed as Event so ionic build --prod for the above code fails with the following error message:

Type 'Event' is missing the following properties from type 'InputCustomEvent': detail, initCustomEvent

Even ionic serve would fail with the same error if it were not for the aot: false setting for the default build in the generated angular.json.

The issue has already been reported and there is even a fix for it, but it did not make it into Ionic 6 as it would involve a breaking change. So until the fix is released, you'll have to settle for one of the workarounds below:

  1. The simplest solution would be to abandon strong typing altogether and just use any for the argument type in the event handler:

    onInputChange(inputEvent: any) {
      console.log(inputEvent.detail.value);
    }
    

    The obvious drawback is that the compiler cannot now detect type errors when accessing InputCustomEvent.

  2. A better solution is to cast the input argument to the correct type before using it. This also allows you to use Event for the type argument:

    onInputChange(event: Event) {
      const inputEvent = event as InputCustomEvent;
      console.log(inputEvent.detail.value);
    }
    

    This provides more type safety than the first alternative, but you can still accidentally call the method with the wrong argument type, either from the template or from code.

  3. The best solution, in my opinion, is to keep the correct argument type in the code and do the casting in the template. Since type casts are not supported in Angular templates, this requires another helper method:

    asInputCustomEvent(event: Event) {
      return event as InputCustomEvent;
    }
    
    onInputChange(inputEvent: InputCustomEvent) {
      console.log(inputEvent.detail.value);
    }
    

    This is how you could call the method from the markup:

    <ion-input
      (ionChange)="onInputChange(asInputCustomEvent($event))"
    ></ion-input>
    

    It's still not completely type-safe, but it makes it harder to make a mistake. And I think this is the most type safety that can be achieved before the problem is fixed in Ionic. The code is perfectly type safe as long as you do not call asInputCustomEvent. You should only call this method from the markup for outputs that have this argument type documented.

You can find a working example project showing all 4 approaches in my GitHub repository.

In Ionic 6, custom component events have strongly typed arguments. Unfortunately, they cannot yet be used in this way in Angular. Until a solution to this problem is released, there are several workarounds. In this post I present all of them that I can think of, each with their advantages and disadvantages.

Get notified when a new blog post is published (usually every Friday):

Copyright
Creative Commons License