Search code examples
angulartypescriptangular-forms

How to define a strongly typed form with a recursive field in Angular?


I would like to define a strongly typed form with a recursive field:

import { FormArray, FormControl, FormGroup } from '@angular/forms';

export interface ICodeSystemConceptForm {
  code: FormControl<string>;
  display: FormControl<string>;
  definition: FormControl<string>;
  concept: FormArray<FormControl<ICodeSystemConceptForm>>;
}

I have a function to create and return the form. Notice the concept field is recursive:

export const initCodeSystemConceptForm = (concept?: fhir4.CodeSystemConcept, codeDisabled = false): ICodeSystemConceptForm => {
  return {
    code: new FormControl(
      {
        value: concept?.code || '',
        disabled: codeDisabled,
      },
      [ Validators.required ]
    ),
    display: new FormControl(concept?.display || ''),
    definition: new FormControl(concept?.definition || ''),
    concept: new FormArray(concept?.concept?.map(nestedConcept => initCodeSystemConceptForm(nestedConcept)) || []),
  });
};

The compiler is complaining that:

Argument of type 'ICodeSystemConceptForm[]' is not assignable to parameter of type 'AbstractControl<any, any>[]'. Type 'ICodeSystemConceptForm' is missing the following properties from type 'AbstractControl<any, any>

I tried setting the FormArray in the interface as:

concept: FormArray<FormGroup<ICodeSystemConceptForm>>

and:

concept: FormArray<ICodeSystemConceptForm>

which results in:

Type 'ICodeSystemConceptForm' does not satisfy the constraint 'AbstractControl<any, any>'. Type 'ICodeSystemConceptForm' is missing the following properties from type 'AbstractControl<any, any>': _parent, _asyncValidationSubscription, value, validator, and 51 more.ts(2344)

and also:

concept: ICodeSystemConceptForm[];

but that results in the same error.

Where am I going wrong?


Solution

  • I had an error elsewhere in my code that was causing compilation to fail. The correct way to represent the field is as such:

    concept: FormArray<FormGroup<ICodeSystemConceptForm>>;