tslint / codelyzer / ng lint error: "las declaraciones for (... in ...) deben filtrarse con una declaración if"

229

Mensaje de error de pelusa:

src / app / detail / edit / edit.component.ts [111, 5]: para (... en ...) las declaraciones deben filtrarse con una declaración if

Fragmento de código (es un código de trabajo. También está disponible en la sección de validación del formulario 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] + ' ';
        }
      }
    }

¿Alguna idea de cómo solucionar este error de pelusa?

choopage - Jek Bao
fuente
Tal vez aceptar una respuesta?
Qwertiy

Respuestas:

241

Para explicar el problema real que señala tslint, una cita de la documentación de JavaScript de for ... en la declaración :

El bucle iterará sobre todas las propiedades enumerables del objeto mismo y aquellas que el objeto herede del prototipo de su constructor (las propiedades más cercanas al objeto en la cadena del prototipo anulan las propiedades de los prototipos).

Entonces, básicamente, esto significa que obtendrá propiedades que podría no esperar obtener (de la cadena de prototipos del objeto).

Para resolver esto, necesitamos iterar solo sobre las propiedades propias de los objetos. Podemos hacer esto de dos maneras diferentes (como lo sugieren @Maxxx y @Qwertiy).

Primera solución

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

Aquí utilizamos el método Object.Keys () que devuelve una matriz de propiedades enumerables propias de un objeto dado, en el mismo orden que el proporcionado por un bucle for ... in (la diferencia es que un bucle for-in enumera propiedades en la cadena prototipo también).

Segunda solución

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

En esta solución, iteramos todas las propiedades del objeto, incluidas las de su cadena de prototipos, pero utilizamos el método Object.prototype.hasOwnProperty () , que devuelve un valor booleano que indica si el objeto tiene la propiedad especificada como propiedad propia (no heredada), para filtrar las propiedades heredadas

akrabi
fuente
2
Me gustaría notar que Object.keyses ES5. Lo único de ES6 es for-of loop. Podemos iterar la matriz en el bucle habitual de 0 a su longitud y sería ES5.
Qwertiy
44
aviso una vez más: si de alguna manera this.formErrorses nulo, for...insimplemente no haga nada, mientras for ... of Object.keys()arrojaría un error.
user3448806
Estoy siguiendo la segunda solución pero aún veo el mensaje de pelusa. Pelusa desactivada por el momento.
raj240
2
¿Por qué no me recomiendan Object.keys(obj).forEach( key => {...}) ?
Ben Carp
268

Una forma más ordenada de aplicar la respuesta de @ Helzgate es posiblemente reemplazar su 'for ... in' con

for (const field of Object.keys(this.formErrors)) {
Maxxx
fuente
66
Esta debería ser la respuesta aceptada, ya que no solo resuelve el problema, sino que también reduce la cantidad de código repetitivo en comparación con condicionales adicionales como if (this.formErrors.hasOwnProperty(field)).
Denialos
1
Tenga cuidado con la respuesta, podría romper sus códigos. Pruebe después de "arreglarlo".
ZZZ
3
Esto en realidad no elimina el error tslint para mí.
HammerN'Songs
77
@ HammerN'Songs comprobar que los ha cambiado a para de vez de para en
Tom
el mismo problema aqui. error no se elimina después de usar esto
llamerr
71
for (const field in this.formErrors) {
  if (this.formErrors.hasOwnProperty(field)) {
for (const key in control.errors) {
  if (control.errors.hasOwnProperty(key)) {
Qwertiy
fuente
13

use 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] + ' ';
    });
  }
});
Helzgate
fuente
2

Si el comportamiento de for (... in ...) es aceptable / necesario para sus propósitos, puede decirle a tslint que lo permita.

en tslint.json, agregue esto a la sección "reglas".

"forin": false

De lo contrario, @Maxxx tiene la idea correcta con

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