Tslint complaints "must be filtered with an if statement" when using a switch

Let's say I have the following method:

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;
}

      

when i run

ng lint

      

I am getting the following error:

for (... in ...) statements should be filtered with an if statement

Taking a look at a similar question , I don't think this answer will apply to my situation. After the switch statement is in the if-else-if ladder category.

tslint should treat a switch statement as a form of an if statement, but it is not !!

+3


source to share


2 answers


I was curious, so I checked the TSlint source code for this rule. It has a function called isFiltered

, which apparently only checks ts.SyntaxKind.IfStatement

, not on 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);
    }

}

      

So if you don't want to convert your object to an array, you need to use the fix from the link you provided. Either Object.keys

or the operator if

:



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

      

Interestingly, you can have any operator if

and the error will go away. There is no check to see if you are calling hasOwnProperty

.

+6


source


This rule is intended to prevent access to properties defined in an object's prototype when used for .. c .

However, you can refactor your code to simply not use it, and make it easier to maintain and develop.

An example would be the following:



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 [];
}

      

You can see a working snippet on the playground here .

+1


source







All Articles