Leonel Elimpe
by Leonel Elimpe
1 min read

Tags

  • Angular
  • Strongly Typed Reactive Forms
  • Reactive Forms

A few days back while looking into strongly typing reactive forms in Angular, I came across this post by Alex Klaus. Given reactive forms don’t currently support strong typing (see issues #13721 and #17000), he suggests making use of Daniele Morosinotto solution which involves leveraging Typescript declaration files (*.d.ts) .

The most elegant solution I’ve seen was provided by Daniele Morosinotto, who suggested leveraging TypeScript declaration files (*.d.ts) to introduce generic interfaces extending the standard ones (e.g. AbstractControl, FormControl, etc.). It doesn’t introduce any new functionality and has no footprint in the compiled JavaScript, but at the same time enforcing strong type checking. Brilliant!

Adopting the solution is straightforward:

  1. Download TypedForms.d.ts from his gist and save it as src/typings.d.ts in your project (Angular 6+ already knows how to use this file, see more in the Angular docs).
  2. Start using the new types (FormGroupTyped<T>, FormControlTyped<T>, etc.) whenever you need a strong type validation (see examples in that gist).

After importing the typings, my typed form declarations now looked like this:

form: FormGroupTyped<MyTypedInterface>;

I however had an issue getting it to work with the FormBuilder service and reached out to him. His suggestion was to just cast the resulted FormGroup to a typed one.

this.form = this.formBuilder.group({
     field1: null,
     field2: null
}) as FormGroupTyped<MyTypedInterface>;

Which did the trick, however… now my IDE bring up an error in the html template file:

<form novalidate [formGroup]="form" (submit)="submit(form.value)"></form>

<!-- Error message: Type FormGroupTyped<MyTypedInterface> is not assignable to type FormGroup -->

I can live with this for now until the Angular Team adds strong typing to Reactive Forms, given am aware of the cause. Please share your thoughts in the comments below, or on Twitter.

Update September 4th, 2019:

I found an easy workaround for the template error. Simple create a getter that returns the typed form cast as a FormGroup, which would cause Angular to complain no more in the template.

  get untypedForm() {
    return this.form as FormGroup;
  }
<form novalidate [formGroup]="untypedForm" (submit)="submit(form.value)"></form>

<!-- No more error message in form template -->