angulareslinttypescript-eslintangular-custom-validators

Unsafe assignment of an `any` value Error on form variables (Angular Validators)


I am trying to get my form variables checked by eslint. Unfortunately, in this file:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

...

  public SignUpForm!: FormGroup;

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit(): void {
    this.SignUpForm = this.formBuilder.group({
      vorname: ['', Validators.required],
      nachname: ['', Validators.required],
      email: ['', Validators.required],
      emailbestaetigt: ['', Validators.required],
      passwort: ['', Validators.required],
      passwortbestaetigt: ['', Validators.required],
      Geburtstag: ['', Validators.required],
      Telefonnummer: ['', Validators.required],
    });
  }

  SignUp(): void {
    const mailformat: RegExp = /^\w+([-]?\w+)*@\w+([-]?\w+)*(\.\w{2,3})+$/;
    if (
      this.SignUpForm.valid &&
      this.SignUpForm.value.vorname.length !== 0 &&
      this.SignUpForm.value.nachname.length !== 0 &&
      this.SignUpForm.value.passwort.length > 7 &&
      this.SignUpForm.value.email.match(mailformat) &&
      this.SignUpForm.value.email === this.SignUpForm.value.emailbestaetigt &&
      this.SignUpForm.value.passwort === this.SignUpForm.value.passwortbestaetigt &&
      this.checkUserAge(this.SignUpForm.value.Geburtstag)
    ) {
      console.log('test');
    } else {
      console.log('test');
    }
  }


I get these errors from the Linter:

34:7   error  Unsafe member access .vorname on an `any` value                         @typescript-eslint/no-unsafe-member-access
35:7   error  Unsafe member access .nachname on an `any` value                        @typescript-eslint/no-unsafe-member-access
36:7   error  Unsafe member access .passwort on an `any` value                        @typescript-eslint/no-unsafe-member-access
37:7   error  Unsafe member access .email on an `any` value                           @typescript-eslint/no-unsafe-member-access
37:7   error  Unsafe call of an `any` typed value                                     @typescript-eslint/no-unsafe-call
38:7   error  Unsafe member access .email on an `any` value                           @typescript-eslint/no-unsafe-member-access
38:39  error  Unsafe member access .emailbestaetigt on an `any` value                 @typescript-eslint/no-unsafe-member-access
39:7   error  Unsafe member access .passwort on an `any` value                        @typescript-eslint/no-unsafe-member-access
39:42  error  Unsafe member access .passwortbestaetigt on an `any` value              @typescript-eslint/no-unsafe-member-access
40:25  error  Unsafe argument of type `any` assigned to a parameter of type `string`  @typescript-eslint/no-unsafe-argument
40:25  error  Unsafe member access .Geburtstag on an `any` value                      @typescript-eslint/no-unsafe-member-access

So basically every variable of the if is somehow of type any, and I don't know how to fix this. Does anyone have an idea?


Solution

  • The angular team decided, that FormGroup.value is of type Partial<T>, in other words, it might or might not contain all of the properties

    
    import { Component} from '@angular/core';
    import { FormGroup, Validators } from '@angular/forms';
    
    ...
    
      public SignUpForm = new FormGroup({
        vorname: new FormControl('', Validators.required),
        nachname: new FormControl('', Validators.required),
        email: new FormControl('', Validators.required),
        emailbestaetigt: new FormControl('', Validators.required),
        passwort: new FormControl('', Validators.required),
        passwortbestaetigt: new FormControl('', Validators.required),
        Telefonnummer: new FormControl('', Validators.required),
      });
    
      SignUp(): void {
        const value = this.SignUpForm.getRawValue();
        if (!this.SignUpForm.valid || !value) {
          return; // invalid
        }
        const mailformat: RegExp = /^\w+([-]?\w+)*@\w+([-]?\w+)*(\.\w{2,3})+$/;
        if (
          value.vorname.length !== 0 &&
          value.nachname.length !== 0 &&
          value.passwort.length > 7 &&
          value.email.match(mailformat) &&
          value.email === value.emailbestaetigt &&
          value.passwort === value.passwortbestaetigt &&
          this.checkUserAge(value.Geburtstag)
        ) {
          console.log('test');
        } else {
          console.log('test');
        }
      }
    

    Yet, you should look into, how custom validators are made and assign them immediately in the constructor. This way, the valid/invalid state would be all that you need to test in order to determine if your form is valid, and your inputs could react to theirs invalid states too.

    function RepeatValidator(otherControlName: string): ValidatorFn {
      return (control: AbstractControl) => {
        const otherControl = (control.parent as FormGroup)?.get(otherControlName);
    
        if (!otherControl) {
          if (isDevMode()) {
            throw new Error(`RepeatValidator: other control ${otherControlName} not found`);
          } else {
            return null;
          }
        }
    
        if (control.value !== otherControl.value) {
          return { repeat: true };
        }
    
        return null;
      };
    }
    
    const SignUpForm = new FormGroup({
      vorname: new FormControl('', {
        nonNullable: true,
        validators: [Validators.required],
      }),
      nachname: new FormControl('', {
        nonNullable: true,
        validators: [Validators.required],
      }),
      email: new FormControl('', {
        nonNullable: true,
        validators: [Validators.required, Validators.email], // email is Angular defined
      }),
      emailbestaetigt: new FormControl('', {
        nonNullable: true,
        validators: [Validators.required, RepeatValidator('email')],
      }),
      passwort: new FormControl('', {
        passwort: true,
        validators: [Validators.required, Validators.minLength(8)],
      }),
      passwortbestaetigt: new FormControl('', {
        nonNullable: true,
        validators: [Validators.required, RepeatValidator('passwort')],
      }),
      Telefonnummer: new FormControl('', {
        nonNullable: true,
        validators: [Validators.required],
      }),
    });