Search code examples
angularangular-formsangular14

Error migrating app from angular 13 to angular 14. Type 'AbstractControl<never, never>' is missing the following properties from type 'FormArray<any>'


After migrating an app from Angular 13, to Angular 14, several errors have appeared in the console when I run npm start:

First error:

error TS2352: Conversion of type 'AbstractControl<never, never>' to
type 'FormArray<any>' may be a mistake because neither type
sufficiently overlaps with the other. If this was intentional, convert
the expression to 'unknown' first.

const statusArray = filterForm.get('status').get('value') as FormArray;

Here is the code:

const filterForm = new FormGroup({});
const filters = portcallFilter;
Object.keys(filters)
  .filter((item) => isNaN(Number(item)))
  .forEach((i) => {        
      filterForm.registerControl(
        i,
        this.formBuilder.group({
          value: '',
          comparison: filters[i],
        })
      );        
  });
const statusArray = filterForm.get('status').get('value') as FormArray;

I have more or less the same issue in other components:

Second error:

error TS2769: No overload matches this call.
  Overload 1 of 2, '(name: "query", control: FormControl<string>): FormControl<string>', gave the following error.
    Argument of type 'string' is not assignable to parameter of type '"query"'.
  Overload 2 of 2, '(this: FormGroup<{ [key: string]: AbstractControl<any, any>; }>, name: string, control: AbstractControl<any, any>): AbstractControl<any, any>', gave the following error.
    The 'this' context of type 'FormGroup<{ query: FormControl<string>; }>' is not assignable to method's 'this' of type 'FormGroup<{ [key: string]: AbstractControl<any, any>; }>'.
      Property 'query' is missing in type '{ [key: string]: AbstractControl<any, any>; }' but required in type '{ query: FormControl<string>; }'

The code is:

public searchForm = new FormGroup({
    query: new FormControl(this.inputSearch ?? ''),
  });

applyFilters(filters: { [key: string]: { [key: string]: string }[] }): void {
    Object.keys(filters).forEach((fil) => {
      this.searchForm.registerControl(
        fil,
        new FormControl(this.filtersValues?.[fil] ?? '')
      );
    });
  }

Third error:

error TS2345: Argument of type 'FormGroup<{ a: FormControl<string>; b: FormControl<string>; c: FormControl<string>; }>' is not assignable to parameter of type 'FormControl<unknown>'.
  Type 'FormGroup<{ a: FormControl<string>; b: FormControl<string>; disclaimer: c<string>; }>' is missing the following properties from type 'FormControl<unknown>': defaultValue, registerOnChange, registerOnDisabledChange

const shipList = this.formBuilder.array([]);
    pda.shipList?.forEach((item) => {
      shipList.push(
        this.formBuilder.group({
          a: item.a,
          b: item.b,
          c: item.c,
        })
      );
    });

Anyone can help?


Solution

  • As the compiler states, you have an issue of type compatibility. Angular 14 introduced Strongly Typed Forms to the Forms API. This allows for better Developer Experience (The intention is not to cause problems in your code and make your life harder). The Strongly Typed Forms allow you to catch runtime bugs at compile time, making your life easier down the road. They also help a lot when it comes to property inference with language services integration in your IDE.

    You have two ways to solve this:

    1- Define a data model and supply it to the strongly typed form (read here)

    2- Use Untyped Forms option for migration from V13 to V14 (read here)