Errore tslint / codelyzer / ng lint: "per le istruzioni (... in ...) devono essere filtrate con un'istruzione if"


229

Messaggio di errore Lint:

src / app / detail / edit / edit.component.ts [111, 5]: per (... in ...) le istruzioni devono essere filtrate con un'istruzione if

Snippet di codice (è un codice funzionante. È disponibile anche nella sezione di convalida del modulo angular.io ):

for (const field in this.formErrors) {
      // clear previous error message (if any)
      this.formErrors[field] = '';
      const control = form.get(field);

      if (control && control.dirty && !control.valid) {
        const messages = this.validationMessages[field];
        for (const key in control.errors) {
          this.formErrors[field] += messages[key] + ' ';
        }
      }
    }

Qualche idea su come correggere questo errore lanugine?


Forse accetti una risposta?
Qwertiy,

Risposte:


241

Per spiegare l'effettivo problema che tslint sta segnalando, una citazione dalla documentazione JavaScript della dichiarazione for ... in :

Il ciclo ripeterà tutte le proprietà enumerabili dell'oggetto stesso e quelle ereditate dall'oggetto dal prototipo del suo costruttore (le proprietà più vicine all'oggetto nella catena del prototipo sovrascrivono le proprietà dei prototipi).

Quindi, fondamentalmente, questo significa che otterrai proprietà che potresti non aspettarti di ottenere (dalla catena di prototipi dell'oggetto).

Per risolvere questo, dobbiamo iterare solo sulle proprietà degli oggetti. Possiamo farlo in due modi diversi (come suggerito da @Maxxx e @Qwertiy).

Prima soluzione

for (const field of Object.keys(this.formErrors)) {
    ...
}

Qui utilizziamo il metodo Object.Keys () che restituisce un array di proprietà enumerabili di un determinato oggetto, nello stesso ordine di quello fornito da un ciclo for ... in (la differenza è che un ciclo for-in enumera le proprietà in anche la catena del prototipo).

Seconda soluzione

for (var field in this.formErrors) {
    if (this.formErrors.hasOwnProperty(field)) {
        ...
    }
}

In questa soluzione ripetiamo tutte le proprietà dell'oggetto, comprese quelle nella sua catena di prototipi, ma utilizziamo il metodo Object.prototype.hasOwnProperty () , che restituisce un valore booleano che indica se l'oggetto ha la proprietà specificata come proprietà propria (non ereditata), per filtrare le proprietà ereditate fuori.


2
Vorrei notare che Object.keysè ES5. L'unica cosa da ES6 è il for-of loop. Possiamo iterare l'array nel normale ciclo da 0 alla sua lunghezza e sarebbe ES5.
Qwertiy,

4
ancora una volta avviso: se in qualche modo this.formErrorsè null, for...innon fare nulla, mentre si for ... of Object.keys()genererebbe un errore.
user3448806,

sto seguendo la seconda soluzione, ma vedo ancora il messaggio lanugine. Per il momento lanugine disabile.
raj240,

2
Perché non mi consigliate Object.keys(obj).forEach( key => {...}) ?
Ben Carp,

268

Un modo più semplice per applicare la risposta di @ Helzgate è probabilmente quello di sostituire il tuo 'for .. in' con

for (const field of Object.keys(this.formErrors)) {

6
Questa dovrebbe essere la risposta accettata in quanto non solo risolve il problema, ma riduce anche la quantità di codice della caldaia rispetto ad altri condizionali come if (this.formErrors.hasOwnProperty(field)).
Denialos,

1
Fai attenzione con la risposta, potrebbe rompere i tuoi codici. Prova dopo averlo "riparato".
ZZZ,

3
Questo in realtà non rimuove l'errore tslint per me.
HammerN'Songs

7
@ HammerN'Songs controllare che è stato modificato a per di invece che per in
Tom

stesso problema qui. l'errore non viene rimosso dopo l'utilizzo di questo
llamerr

71
for (const field in this.formErrors) {
  if (this.formErrors.hasOwnProperty(field)) {
for (const key in control.errors) {
  if (control.errors.hasOwnProperty(key)) {

13

usa Object.keys:

Object.keys(this.formErrors).map(key => {
  this.formErrors[key] = '';
  const control = form.get(key);

  if(control && control.dirty && !control.valid) {
    const messages = this.validationMessages[key];
    Object.keys(control.errors).map(key2 => {
      this.formErrors[key] += messages[key2] + ' ';
    });
  }
});

2

Se il comportamento di for (... in ...) è accettabile / necessario per i tuoi scopi, puoi dire a tslint di permetterlo.

in tslint.json, aggiungilo alla sezione "regole".

"forin": false

Altrimenti, @Maxxx ha l'idea giusta con

for (const field of Object.keys(this.formErrors)) {

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.