Tslint: strikt-boolesche-Ausdrücke sollten nicht für logische Operatoren ausgelöst werden, die in einem nicht-booleschen Kontext verwendet werden

Erstellt am 4. Okt. 2017  ·  18Kommentare  ·  Quelle: palantir/tslint

Fehlerbericht

  • __TSLint-Version__: 5.7
  • __TypeScript-Version__: 2.5.3
  • __TSLint ausführen über__: CLI

TypeScript-Code wird linted

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

mit tslint.json Konfiguration:

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

Tatsächliches Verhalten

Bericht über 2 Fehler erhalten:
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.

Erwartetes Verhalten

Es werden keine Fehler gemeldet. Ich verwende den logischen Operator || , um einen Standardwert für den Parameter bereitzustellen (ich weiß, dass ich eine Standarddeklaration für einen Funktionsparameter verwenden könnte, der Ausschnitt dient nur zur Veranschaulichung des allgemeinen Problems). Es gibt nirgendwo boolean im Spiel: weder die Eingabe noch die Ausgabe des Ausdrucks.

Fixed Bug

Hilfreichster Kommentar

Meiner Meinung nach sollte strict-boolean-expressions nur den linken Operanden von && und || prüfen. Diese Operatoren sind (im Wesentlichen) Zucker für Ternäre: a && b ist gleich a ? b : a und a || b ist gleich a ? a : b . Wenn man so darüber nachdenkt, ist es sehr sinnvoll, das RHS zu ignorieren, und es würde das Verhalten für die Kurzschlussoperatoren mit dem Verhalten für Ternäre in Einklang bringen.

Wenn dann das Ganze ist innerhalb einer if / for / while, strict-boolean-conditions ins Spiel kommen könnte und prüfen Sie den gesamten Ausdruck. Ich denke, dies würde alle nützlichen Fälle abdecken, und ich könnte diese Regel wieder aktivieren.

Der Code, der dies für mich als Problem markierte, war dieses dokumentierte allgemeine React-Muster :

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 Sein Code

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.

Die Absicht des Ausdrucks hängt vom LHS ab, daher würde mein Vorschlag, den RHS zu ignorieren, auch sein Problem lösen.

Alle 18 Kommentare

Die Gedanken? Gebete? Vorschläge, wo/wie man anfangen soll?

@marcind können Sie Beispiele dafür geben, wie es sich anders verhalten sollte als das Drehen der Regel?

Entschuldigung, welcher Teil meiner ursprünglichen Einreichung ist unklar?

Ich denke, mein Punkt ist, dass diese Regel nur in einem "booleschen Kontext" ausgeführt werden sollte, mir fallen zwei Fälle ein:

  1. Wird in einem if , while oder for
  2. Einer Variablen vom Typ boolean zugewiesen.

Die Regel sollte nicht ausgeführt werden, wenn ich versuche, einen Standardwert oder eine Kurzschlussauswertung bereitzustellen

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

@marcind die Beispiele aus deinem letzten Beitrag würden funktionieren, wenn du die Option "allow-undefined-union" .

Der andere Teil Ihrer Anfrage sollte eine separate Regel namens strict-boolean-conditions die nur if , for , while , do ... while und bedingte prüft Ausdrücke ( x ? y : z ).
Ich kann mir vorstellen, dass es nur die Art des gesamten Zustands und nicht seine Bestandteile überprüft:

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
}

Vielleicht kann dies eine Option für die bestehende Regel anstelle einer neuen Regel sein...

Meiner Meinung nach sollte strict-boolean-expressions nur den linken Operanden von && und || prüfen. Diese Operatoren sind (im Wesentlichen) Zucker für Ternäre: a && b ist gleich a ? b : a und a || b ist gleich a ? a : b . Wenn man so darüber nachdenkt, ist es sehr sinnvoll, das RHS zu ignorieren, und es würde das Verhalten für die Kurzschlussoperatoren mit dem Verhalten für Ternäre in Einklang bringen.

Wenn dann das Ganze ist innerhalb einer if / for / while, strict-boolean-conditions ins Spiel kommen könnte und prüfen Sie den gesamten Ausdruck. Ich denke, dies würde alle nützlichen Fälle abdecken, und ich könnte diese Regel wieder aktivieren.

Der Code, der dies für mich als Problem markierte, war dieses dokumentierte allgemeine React-Muster :

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 Sein Code

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.

Die Absicht des Ausdrucks hängt vom LHS ab, daher würde mein Vorschlag, den RHS zu ignorieren, auch sein Problem lösen.

Ich stimme zu, dass die Überprüfung des RHS von && und || ein Fehler ist.


Ich bin auch geneigt, die Schecks für den LHS von && , || und den Operanden von ! . Diese sollten nur überprüft werden, ob der Ausdruck immer wahr oder immer falsch ist.
Damit bleiben nur die Bedingungen von if , for , while , do ... while und bedingte Ausdrücke für die strikte Prüfung, um nur boolesche Werte (oder was auch immer sonst konfiguriert ist) zuzulassen ). Gedanken @adidahiya?

Derzeit würde die Aktivierung dieser Regel mit verfügbaren Konfigurationsoptionen tagelange Arbeit mit unserer Codebasis erfordern. :(

Ich habe es aktiviert in der Hoffnung, dass es die implizite Konvertierung von number , null oder undefined in boolean . Zum Beispiel:

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


md5-d563d6246c0e981c16f8a2b3d7f53974





md5-430ec08bab82330fa4e519419e9ad014




However I find the following uses acceptable:



md5-70351fc6fdb328ee060919d6974e2cf4



```tsx


md5-036fd2ddd516eac8e1379cdcb9ac2b9a


Ich denke, das stimmt mit dem überein, was @marcind vorschlägt .

Ich neige auch dazu, die Checks für den LHS von && zu lockern, || und der Operand von !.

@ajafff würde das if (!!array.length) oder if (!possiblyNull) legalisieren?

@ajafff @adidahiya weitere Gedanken hier? Ich bin in genau der gleichen Situation wie @rhys-vdw.

Schamlose Werbung für mein eigenes Projekt:
Seit meiner letzten Aktivität in dieser Ausgabe habe ich meinen eigenen Linter erstellt, das Fimbullinter-Projekt . Lesen Sie die Dokumentation für einen schnellen Start: https://github.com/fimbullinter/wotan/blob/master/packages/wotan/README.md

Es enthält eine Regel no-useless-predicate , nach der Sie möglicherweise suchen. Es ist eine Kombination aus TSLints strict-type-predicates und strict-boolean-expressions , jedoch mit einigen großen Unterschieden:

Im Gegensatz zu TSLints strict-type-predicates funktioniert es auch ohne --strictNullChecks und behandelt Typparameter und leere Objekttypen korrekt. (wahrscheinlich nicht so interessant für Leute, die diese Ausgabe abonniert haben)
Der Hauptunterschied zu strict-boolean-expressions von TSLint besteht darin, dass es nicht erfordert, dass alles ein boolescher

Einige Beispiele:

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

Ich möchte mich mit dem folgenden Anwendungsfall aus meinem tatsächlichen Code einklinken:

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
}

Wie Sie sehen, verwende ich || , um Standardwerte anzugeben, wenn der LHS nicht definiert ist. Gibt es eine prägnante Möglichkeit, tslint verstehen, dass dies strict-boolean-expressions ? Andernfalls bin ich gezwungen, diese Befehle zum Deaktivieren/Aktivieren zu verwenden. (Überraschenderweise ist dies nur ein Problem mit aktivierter Typprüfung und nicht in VSCode.)

Diese Verwendung ist Standard und in JavaScript sehr verbreitet und praktisch und sollte definitiv nicht dazu führen, dass diese Regel fehlschlägt.

IMHO sollten die RHS von && und || nicht überprüft werden, um einen Kurzschluss zu ermöglichen. Dies sollte das Standardverhalten sein (oder es sollte zumindest eine Option wie allow-any-rhs ). Derzeit kann ich strict-boolean-expressions , da es in unserer Codebasis viele Kurzschlüsse gibt.

Die Überprüfung des LHS sollte IMHO unverändert bleiben, da die Verwendung von string oder number als LHS gefährlich sein kann, siehe dieses Beispiel:

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

Dies ist gefährlich, da viele Entwickler nicht verstehen, dass nicht nur null sondern auch 0 und "" defaultValue zurückgeben.

Ich musste mich mit großen Fehlern in meinem Projekt auseinandersetzen, weil Entwickler nicht berücksichtigten, dass "" und 0 ebenfalls falsch sind. Diese Art von Code zu verhindern, ist mein primärer Anwendungsfall für strict-boolean-expressions .

Behoben in https://github.com/palantir/tslint/pull/4159 benötigen Sie nur eine Überprüfung von einem Mitarbeiter.

Hoppla, wollte nur klarstellen, dass eines meiner Beispiele schlecht war:

const x = possiblyUndefined || 5;

Das sollte nicht funktionieren, weil possiblyUndefined 0 könnte, was ein logischer Fehler sein könnte. Sieht so aus , als würde die PR von

enthält für Array ist eine ES7-Funktion.
Sie müssen Ihre ts-Konfiguration ändern, um ES7 oder ESNEXT zu verwenden 🦄

Grüße,

@rimiti Hallo, ich kann nicht herausfinden, worauf du dich

@dobesv Oh, du hast recht, sorry ;)

behoben durch #4159, wird in der nächsten Version verfügbar sein

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen