web-dev-qa-db-fra.com

tslint se plaignant "les instructions doivent être filtrées avec une instruction if" lors de l'utilisation du commutateur

Disons que j'ai la méthode suivante:

getErrorMessage(state: any, thingName?: string) {
    const thing: string = state.path || thingName;
    const messages: string[] = [];
    if (state.errors) {
        for (const errorName in state.errors) {
            switch (errorName) {
                case 'required':
                    messages.Push(`You must enter a ${thing}`);
                    break;
                case 'minlength':
                    messages.Push(`A ${thing} must be at least ${state.errors['minlength'].requiredLength}characters`);
                    break;
                case 'pattern':
                    messages.Push(`The ${thing} contains illegal characters`);
                    break;
                case 'validateCardNumberWithAlgo':
                    messages.Push(`Card doesnt pass algo`);
                    break;
            }
        }
    }
    return messages;
}

quand je cours

ng lint

J'obtiens l'erreur suivante:

pour les instructions (... in ...) doivent être filtrées avec une instruction if

Jetant un oeil à similaire question Je ne pense pas que la réponse serait applicable à ma situation. Après tout, l'instruction switch se trouve dans la catégorie de l'échelle if-else-if.

tslint devrait considérer l'instruction switch comme une forme d'instruction if mais ce n'est pas le cas?!

16
MHOOS

Cela m'a rendu curieux, j'ai donc vérifié le code source TSlint pour cette règle. Il a une fonction appelée isFiltered qui ne semble vérifier que ts.SyntaxKind.IfStatement, pas pour ts.SyntaxKind.SwitchStatement.

function isFiltered({statements}: ts.Block): boolean {
    switch (statements.length) {
        case 0: return true;
        case 1: return statements[0].kind === ts.SyntaxKind.IfStatement;
        default:
            return statements[0].kind === ts.SyntaxKind.IfStatement && nodeIsContinue((statements[0] as ts.IfStatement).thenStatement);
    }

}

Donc, à moins que vous ne souhaitiez convertir votre objet en tableau, vous devrez utiliser un correctif à partir du lien que vous avez fourni. Non plus Object.keys, ou une instruction if:

    for (const errorName in state.errors) {
      if (state.errors.hasOwnProperty(errorName)) {
        switch (errorName) {

La chose intéressante est que vous pouvez avoir n'importe quel type d'instruction if et l'erreur disparaîtra. Il n'y a aucune vérification pour voir si vous appelez hasOwnProperty.

24
Frank Modica

La règle est destinée à vous empêcher d'accéder aux propriétés définies sur le prototype d'objet lors de l'utilisation de pour .. dans .

Vous pouvez cependant refactoriser le code pour ne pas l'utiliser, et le rendre plus facile à maintenir et à développer également.

Un exemple serait ceci:

interface ErrorMessageFactory {
  (thing: string, state?): string
}

type Errors = 'required' | 'minlength' | 'pattern' | 'validateCardNumberWithAlgo'

let errorFactory: {[e in Errors]: ErrorMessageFactory} = {
  required: (thing) => `You must enter a ${thing}`,
  minlength: (thing, state) => `A ${thing} must be at least ${state.errors['minlength'].requiredLength}characters`,
  pattern: (thing) => `The ${thing} contains illegal characters`,
  validateCardNumberWithAlgo: (thing) => `Card doesnt pass algo`
}



function getErrorMessage(state: any, thingName?: string) {
  if (state.errors) {
    return state.errors.map((error) => errorFactory[error](thingName, state));
  }
  return [];
}

Vous pouvez voir un extrait de travail dans la cour de récréation ici .

7
toskv