title: Angular 6 - Expected validator to return Promise or Observable in async validator
body: <p>In my Angular 6 app I have async validator for checking if typed email is already registered but right now I'm getting 'Expected validator to return Promise or Observable' and I don't really know why.</p>
  
  <pre><code>import { UserService } from '../user/service/user.service';
  import { AbstractControl, ValidationErrors, AsyncValidator } from '@angular/forms';
  import * as validationUtils from '../validation/validation-utils';
  import { Injectable } from '@angular/core';
  import { of, Observable } from 'rxjs';
  import { map } from 'rxjs/operators';
  
  @Injectable({
    providedIn: 'root'
  })
  export class EmailExistValidator implements AsyncValidator {
    constructor(private userService: UserService) {
    }
  
    validate(emailControl: AbstractControl): Promise&lt;ValidationErrors | null&gt; | Observable&lt;ValidationErrors | null&gt; {
      const email = emailControl.value;
  
      if (new RegExp(validationUtils.emailRegex).test(email)) {
        this.userService
        .checkIfEmailExist(email)
        .pipe(
          map(
          (data) =&gt; {
            return {emailExist: true};
          },
          (error) =&gt; {
            return null;
          }
        ));
      }
        return of(null);
    }
  }
  </code></pre>
  
  <p>register-component.ts</p>
  
  <pre><code>  createForm(): FormGroup {
      return this.formBuilder.group({
        email: ['',
        [Validators.required, Validators.email],
        [EmailExistValidator.bind(this)]],
        username: ['', [Validators.required,
          Validators.pattern(validationUtils.usernameRegex)]],
        password: ['', [Validators.required,
          Validators.pattern(validationUtils.passwordRegex)]],
        repeatPassword: ['', [Validators.required]]
    }, {
      validator: EqualPasswordValidator.validate
    });
    }
  </code></pre>
  
  <p><strong>Edit 17.08.2018</strong>
  As @Paulie suggested I changed validator declaration in formbuilder from <em>.bind</em> to pointing to <em>validate</em> function and with some tweaks to his proposition now everything works! </p>
  
  <p>Final code:</p>
  
  <p>register-component.ts</p>
  
  <pre><code>  constructor(
      private formBuilder: FormBuilder,
      private userService: UserService,
      private emailExistsValidator: EmailExistsValidator,
      private usernameExistsValidator: UsernameExistsValidator) { }
  
    ngOnInit() {
      this.registerForm = this.createForm();
    }
  
    createForm(): FormGroup {
      return this.formBuilder.group({
        email: ['',
        [Validators.required, Validators.email],
        [this.emailExistsValidator.validate]],
        username: ['', [Validators.required,
          Validators.pattern(validationUtils.usernameRegex)],
          [this.usernameExistsValidator.validate]],
        password: ['', [Validators.required,
          Validators.pattern(validationUtils.passwordRegex)]],
        repeatPassword: ['', [Validators.required]]
    }, {
      validator: EqualPasswordValidator.validate
    });
    }
  </code></pre>
  
  <p>email-exists-validator.ts</p>
  
  <pre><code>import { UserService } from '../user/service/user.service';
  import { AbstractControl, ValidationErrors, AsyncValidator } from '@angular/forms';
  import * as validationUtils from './validation-utils';
  import { Injectable } from '@angular/core';
  import { of, Observable } from 'rxjs';
  import { map, catchError } from 'rxjs/operators';
  
  @Injectable({
    providedIn: 'root'
  })
  export class EmailExistsValidator implements AsyncValidator {
      static userService: UserService;
  
    constructor(private userService: UserService) {
      EmailExistsValidator.userService = userService;
    }
  
    validate(emailControl: AbstractControl): Promise&lt;{ [key: string]: any } | null&gt;
    | Observable&lt;{ [key: string]: any } | null&gt;  {
  
      const email = emailControl.value;
  
      if (new RegExp(validationUtils.emailRegex).test(email)) {
          return EmailExistsValidator.userService
          .checkIfEmailExist(email)
          .pipe(
            map(data =&gt; ({emailExist: true})),
            catchError(error =&gt; of(null))
          );
        }
  
        return of(null);
  
  }
  }
  </code></pre>