Tslint: strict-boolean-expressionsは、非ブールコンテキストで使用される論理演算子に対して起動しないでください

作成日 2017年10月04日  ·  18コメント  ·  ソース: palantir/tslint

バグレポート

  • __TSLintバージョン__:5.7
  • __TypeScriptバージョン__:2.5.3
  • __TSLintの実行__:CLI

リンティングされているTypeScriptコード

// code snippet
function valueOrDefault(a?: string) {
  return a || "the default";
}

tslint.json構成の場合:

{
  "defaultSeverity": "error",
  "extends": [
      "tslint:all"
  ]
}

実際の動作

2つのエラーのレポートを取得する:
strict-boolean-expressions This type is not allowed in the operand for the '||' operator because it could be undefined. Only booleans are allowed.
strict-boolean-expressions This type is not allowed in the operand for the '||' operator because it is always truthy. Only booleans are allowed.

予想される行動

エラーは報告されていません。 論理||演算子を使用して、パラメーターのデフォルト値を指定しています(関数パラメーターのデフォルト宣言を使用できることはわかっています。スニペットは、一般的な問題を説明するためのものです)。 式の入力も出力も、どこにもbooleanはありません。

Fixed Bug

最も参考になるコメント

私の意見では、 strict-boolean-expressions&&||の左側のオペランドのみをチェックする必要があります。 これらの演算子は(本質的に)三元の砂糖です: a && ba ? b : aに等しく、 a || ba ? a : b等しくなります。 これらの用語で考えると、RHSを無視することは非常に理にかなっており、短絡演算子の動作を3値の動作と一致させることになります。

次に、すべてがif / for / while内にある場合、 strict-boolean-conditionsが機能し、全体的な式を確認できます。 これですべての便利なケースがカバーされると思います。このルールをオンに戻すことができます。

これを私にとって問題としてフラグを立てたコードは、この文書化された一般的なReactパターンでした:

function Foo(props: { showToggle: boolean }) {
  return <div>{props.showToggle && <Toggle />}</div>;
}
ERROR: 2:36 strict-boolean-expressions This type is not allowed in the operand for the '&&' operator because it is always truthy. Allowed types are boolean, null-union, undefined-union, string, or number.

@ajafff RHSが一定であるため、ルールのすべてのオプションが有効になっている場合でも、彼のコードはリンターを渡しません。

export function valueOrDefault(a?: string) {
  return a || "the default";
}
"strict-boolean-expressions": [true, "allow-null-union", "allow-undefined-union", "allow-string", "allow-number", "allow-mix"]
ERROR: 2:15 strict-boolean-expressions This type is not allowed in the operand for the '||' operator because it is always truthy. Allowed types are boolean, null-union, undefined-union, string, or number.

式の意図はLHSを条件としているので、RHSを無視するという私の提案は彼の問題も解決するでしょう。

全てのコメント18件

考え? 祈り? どこから/どのように始めるべきかについての提案?

@marcindは、ルールの変更とは異なる動作をする方法の例を提供できますか?

申し訳ありませんが、最初の提出が不明確な部分はどれですか?

私のポイントは、このルールは「ブールコンテキスト」でのみ実行する必要があるということだと思います。次の2つのケースが考えられます。

  1. ifwhile 、またはfor
  2. booleanとして入力された変数に割り当てられます。

デフォルト値または短絡評価を提供しようとすると、ルールが実行されないはずです

  1. const a: string = potentiallyUndefinedString || "the default";
  2. const a: string | undefined = potentiallyUndefinedObject && potentiallyUndefinedObject.getString()

@marcind "allow-undefined-union"オプションを使用すると、前回の投稿の例が機能します。

リクエストの他の部分は、 ifforwhiledo ... whileのみをチェックするstrict-boolean-conditionsという名前の別のルールである必要があります。式( x ? y : z )。
状態全体のタイプのみをチェックし、構成要素はチェックしないと想像できます。

function foo(a: boolean, b?: boolean) {
    if (b || a) {} // passes, result is always boolean
    if (b && a) {} // fails, result is boolean | undefined
    if (a || b) {} // fails, result is boolean | undefined
    if (a || !!b) {} // passes
}

たぶん、これは新しいルールではなく、既存のルールのオプションになる可能性があります...

私の意見では、 strict-boolean-expressions&&||の左側のオペランドのみをチェックする必要があります。 これらの演算子は(本質的に)三元の砂糖です: a && ba ? b : aに等しく、 a || ba ? a : b等しくなります。 これらの用語で考えると、RHSを無視することは非常に理にかなっており、短絡演算子の動作を3値の動作と一致させることになります。

次に、すべてがif / for / while内にある場合、 strict-boolean-conditionsが機能し、全体的な式を確認できます。 これですべての便利なケースがカバーされると思います。このルールをオンに戻すことができます。

これを私にとって問題としてフラグを立てたコードは、この文書化された一般的なReactパターンでした:

function Foo(props: { showToggle: boolean }) {
  return <div>{props.showToggle && <Toggle />}</div>;
}
ERROR: 2:36 strict-boolean-expressions This type is not allowed in the operand for the '&&' operator because it is always truthy. Allowed types are boolean, null-union, undefined-union, string, or number.

@ajafff RHSが一定であるため、ルールのすべてのオプションが有効になっている場合でも、彼のコードはリンターを渡しません。

export function valueOrDefault(a?: string) {
  return a || "the default";
}
"strict-boolean-expressions": [true, "allow-null-union", "allow-undefined-union", "allow-string", "allow-number", "allow-mix"]
ERROR: 2:15 strict-boolean-expressions This type is not allowed in the operand for the '||' operator because it is always truthy. Allowed types are boolean, null-union, undefined-union, string, or number.

式の意図はLHSを条件としているので、RHSを無視するという私の提案は彼の問題も解決するでしょう。

&&||のRHSをチェックするのはバグであることに同意します。


また、LHSの&&|| 、およびオペランドの!のチェックを緩和する傾向があります。 これらは、表現が常に真実であるか、常に偽であるかを確認する必要があります。
これにより、 ifforwhiledo ... while条件と、ブール値(またはその他の構成済みのもの)のみを許可する厳密なチェックの条件式のみが残ります。 )。 @adidahiyaを考えますか?

現在、利用可能な構成オプションを使用してこのルールを有効にすると、コードベースで数日間の作業が必要になります。 :(

numbernullまたはundefinedからbooleanへの暗黙の変換を防ぐことを期待して有効にしました。 例えば:

if (!!array.length) { /* ... */ }


md5-d563d6246c0e981c16f8a2b3d7f53974





md5-430ec08bab82330fa4e519419e9ad014




However I find the following uses acceptable:



md5-70351fc6fdb328ee060919d6974e2cf4



```tsx


md5-036fd2ddd516eac8e1379cdcb9ac2b9a


これは@marcindが示唆していることと一致すると思います。

また、&&のLHSのチェックを緩和する傾向があります|| および

@ajafffはこれでif (!!array.length)またはif (!possiblyNull)合法化しますか?

@ajafff @adidahiyaここでさらに考えはありますか? 私は@ rhys-vdwとまったく同じ状況にあります。

恥知らずに自分のプロジェクトを宣伝する:
この号の最後の活動以来、私は自分のリンターであるFimbullinterプロジェクトを作成しました。 クイックスタートについては、ドキュメントをお読みください//github.com/fimbullinter/wotan/blob/master/packages/wotan/README.md

ルールno-useless-predicateが含まれています。これは、探しているものである可能性があります。 これはTSLintのstrict-type-predicatesstrict-boolean-expressions組み合わせですが、いくつかの大きな違いがあります。

TSLintのとは対照的にstrict-type-predicatesもせずに動作します--strictNullChecksと正しく型パラメータと、空のオブジェクト・タイプを処理します。 (おそらく、この問題を購読している人々にとってはそれほど面白くありません)
TSLintのstrict-boolean-expressionsとの主な違いは、すべてがブール値である必要がないことです(暗黙の強制は検出されません)。 それは、すべての条件がおそらく真実で偽物である必要があるだけです。

いくつかの例:

if (0) {} // error, always falsy
if (1) {} // error, always truthy
declare let array: string[];
if (array.length) {} // no error
if (!array.length) {} // no error
if (!!array.length) {} // no error
if (array.length === undefined) {} // error, condition is always false
if (!!false) {} // 2 errors, because of the double negation of an always falsy value

declare let someString: string;
return someString || 'some default string'; // no error, because 'someString' might be falsy

declare const foo: 'bar' | 'baz';
return foo || 'bas'; // error, 'foo' is always truthy

declare let optionalFunction: (() => void) | undefined;
optionalFunction && optionalFunction(); // no error

私の実際のコードから、次のユースケースを紹介したいと思います。

export interface ILoggingRule {
    readonly isFinal?: boolean;
    readonly loggerNamePattern?: string;
    readonly maxLogLevel?: LogLevel;
    readonly minLogLevel?: LogLevel;
    readonly target: Target;
}

// ...

/**
 * Creates an instance of LoggingRule.
 * <strong i="6">@param</strong> options Configuration options of the logging rule.
 */
public constructor(options: ILoggingRule) {
    // tslint:disable:strict-boolean-expressions
    this.isFinal = options.isFinal || false;
    this.loggerNamePattern = options.loggerNamePattern || "*";
    this.maxLogLevel = options.maxLogLevel || LogLevel.Fatal;
    this.minLogLevel = options.minLogLevel || LogLevel.Trace;
    this.target = options.target;
    // tslint:enable:strict-boolean-expressions
}

ご覧のとおり、LHSが未定義の場合、デフォルト値を示すために||を使用しています。 tslintこれがstrict-boolean-expressions準拠していることを理解させる簡潔な方法はありますか? それ以外の場合は、これらの無効化/有効化コマンドを使用する必要があります。 (驚くべきことに、これはタイプチェックが有効になっている場合の問題であり、VSCodeでは問題ではありません。)

この使用法は標準的であり、JavaScriptでは非常に一般的で便利であり、このルールが失敗する原因となることは絶対にありません。

短絡を考慮して、 &&||のRHSをチェックしないでください。 これがデフォルトの動作である必要があります(または、少なくともallow-any-rhsようなオプションがあるはずです)。 現在、コードベースに多くの短絡があるため、 strict-boolean-expressions使用できません。

LHSは危険である可能性があるため、 stringまたはnumberを使用するため、LHSのチェックはそのままIMHOのままにする必要があります。次の例を参照してください。

function foo(x: string | number | null) {
  return x || defaultValue;
}

多くの開発者は、 nullだけでなく、 0""によってdefaultValueが返されることを理解できないため、これは危険です。

""0も誤っていることを開発者が考慮に入れていないため、プロジェクトの主要なバグに対処する必要がありました。 この種のコードを防ぐことは、 strict-boolean-expressions私の主なユースケースです。

https://github.com/palantir/tslint/pull/4159で修正されましたが、共同編集者からのレビューが必要です。

おっと、私の例の1つが悪かったことを明確にしたかっただけです。

const x = possiblyUndefined || 5;

possiblyUndefined0ある可能性があり、論理エラーである可能性があるため、これは機能しないはずです。 @dobesvのPRはここで機能するようです。

アレイのインクルードはES7の機能です。
ES7またはESNEXTを使用するには、構成を変更する必要があります🦄

よろしく、🚀

@rimitiこんにちは、あなたが何を指しているのか

@dobesvああ、ごめんなさい;)

#4159で修正され、次のリリースで利用可能になります

このページは役に立ちましたか?
0 / 5 - 0 評価