web-dev-qa-db-ja.com

tslintがswitchを使用するときに「ステートメントはifステートメントでフィルターする必要がある」と文句を言います

次の方法があるとしましょう:

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

私が走るとき

ng lint

次のエラーが表示されます。

for(... in ...)ステートメントは、ifステートメントでフィルターする必要があります

同様の question を見てみると、その答えは私の状況に当てはまるとは思いません。すべてのswitchステートメントは、if-else-ifラダーのカテゴリに属します。

tslintは、switchステートメントをifステートメントの形式と見なすべきですが、そうではありません!?

16
MHOOS

これは私を不思議に思わせたので、このルールの TSlintソースコード をチェックアウトしました。 isFilteredという関数があり、ts.SyntaxKind.IfStatementではなく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);
    }

}

そのため、オブジェクトを配列に変換する場合を除き、指定したリンクの修正を使用する必要があります。 Object.keysまたはifステートメントのいずれか:

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

興味深いのは、あらゆる種類のifステートメントを使用でき、エラーがなくなることです。 hasOwnPropertyを呼び出しているかどうかを確認するチェックはありません。

24
Frank Modica

このルールは、for .. inを使用するときに、オブジェクトプロトタイプで定義されたプロパティにアクセスできないようにすることを目的としています。

ただし、それを使用しないようにコードをリファクタリングし、同様に保守および開発を容易にすることができます。

例は次のとおりです。

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

プレイグラウンドで動作するスニペットを見ることができます here

7
toskv