'Angular 8 - not assignable to AsyncValidatorFn

I'm trying to create custom validator function in reactive form. Code:

form.component.ts

...
    form = new FormGroup({
        username: new FormControl('', [
            Validators.required,
            Validators.minLength(3)
        ],
            UsernameService.isUnique
        )
    });
...

username.service.ts

...
    static isUnique(control: AbstractControl): Promise<ValidationErrors | null> {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve({ notUnique: true });
            }, 2000);
        });
    }
...

There is an error shown while hovering on UsernameService.isUnique -

"Argument type (control: AbstractControl) => Promise< ValidationErrors | null > is not assignable to parameter type AsyncValidatorFn | AsyncValidatorFn[] | null"

Why this error exists? According to documentation (https://angular.io/api/forms/AsyncValidatorFn) I used proper call signature of AsyncValidatorFn.



Solution 1:[1]

There was a typescript problem - importing bad type(?) of Promise, I had to add install this module

npm i --save bluebird

and use this as Promise import in component:

import * as Promise from 'bluebird';

Solution 2:[2]

The solution is actually very simple --

add "as AsyncValidatorFn" behind "UsernameService.isUnique":

      UsernameService.isUnique as AsyncValidatorFn

or add AsyncValidatorFn before it within "<>":

      <AsyncValidatorFn>UsernameService.isUnique

Of course, AsyncValidatorFn needs to be imported:

      import { AsyncValidatorFn } from '@angular/forms';

Example in practice:

The following picture shows that there is an error WITHOUT "as AsyncValidatorFn":

enter image description here

The error message is about the same:

      Argument of type '(control: FormControl) => 
      Promise<any> | Observable<any>' is not assignable to
      parameter of type 'AsyncValidatorFn | AsyncValidatorFn[]'

The following shows that the error DISAPPEARED after "as AsyncValidatorFn" is added (behind):

enter image description here

or (before):

enter image description here

The following is the "forbiddenEmails" function:

enter image description here

Actually, you can solve many similar problems in the same way.

Solution 3:[3]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jakub1998
Solution 2
Solution 3 William