strict-boolean-expressions should not fire for logical operators used in a non-boolean context #3279
Comments
Thoughts? Prayers? Suggestions on where/how to get started? |
@marcind can you provide examples on how it should behave differently from turning of the rule? |
Sorry, which part my initial submission is unclear? I guess my point is that this rule should only run in a "boolean context", I can think of two cases:
The rule should not run when I'm trying to provide a default value or short-circuit evaluation
|
@marcind the examples from your last post would work if you use the The other part of your request should be a separate rule named 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
} Maybe this can be an option for the existing rule instead of a new rule... |
In my opinion, Then, if the whole thing is inside an if/for/while, The code that flagged this as a problem for me was this documented common React pattern: function Foo(props: { showToggle: boolean }) {
return <div>{props.showToggle && <Toggle />}</div>;
}
@ajafff His code doesn't pass the linter for me, even with all the rule's options enabled, because of the constant RHS:
The intent of the expression is a conditional on the LHS, so my proposal of ignoring the RHS would solve his problem as well. |
I agree that checking the RHS of I'm also inclined to relax the checks for the LHS of |
Disabled the rule until it's fixed at <palantir/tslint#3279>
Currently enabling this rule with available configuration options would necessitate days of work with our code base. :( I enabled it hoping it would prevent implicit conversion of if (!!array.length) { /* ... */ } <div>
{array.length && <div />}
</div> if (possiblyNull) {
callFunction(possiblyNull)
} However I find the following uses acceptable: const x = possiblyUndefined || 5; // commented below, this was a mistake <div>
{array.length > 0 && <div />}
</div> I think this agrees with what @marcind suggests.
@ajafff would this legalize |
@ajafff @adidahiya any further thoughts here? I'm in the exact same situation as @rhys-vdw. |
Shamelessly advertising my own project: It contains a rule In contrast to TSLint's Some examples: 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 |
I'd like to chime in with the following use case from my actual code: export interface ILoggingRule {
readonly isFinal?: boolean;
readonly loggerNamePattern?: string;
readonly maxLogLevel?: LogLevel;
readonly minLogLevel?: LogLevel;
readonly target: Target;
}
// ...
/**
* Creates an instance of LoggingRule.
* @param 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
} As you can see I am using |
This usage is standard and extremely common and convenient in JavaScript, and should definitely not trigger this rule to fail. |
IMHO the RHS of Checking the LHS should remain as-is IMHO, since using function foo(x: string | number | null) {
return x || defaultValue;
} This is dangerous since many developers will fail to understand that not just I have had to deal with major bugs in my project, due to developers failing to take into consideration that |
Fixed in #4159 just need a review from a collaborator. |
Oops, just wanted to clarify that one of my examples was bad: const x = possiblyUndefined || 5; That shouldn't work because |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
fixed by #4159, will be available in the next release |
The next tslint version will include an option to disable this specific check (palantir/tslint#3279)
* build: adds more liniting options * refactor: fixes `Unsafe use of expression of type 'any'` lint errors * refactor: fixes `Expression is always true` lint errors * refactor: mark private member as readonly * refactor: fixes `his type is not allowed in the 'if' condition because it could be a string` lint error * refactor: ignores two lint errors The next tslint version will include an option to disable this specific check (palantir/tslint#3279) * build: enables linting before publishing, fixes #5
Bug Report
TypeScript code being linted
with
tslint.json
configuration:Actual behavior
Getting report of 2 errors:
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.
Expected behavior
No errors being reported. I'm using the logical
||
operator to provide a default value for the parameter (I know I could use a function parameter default declaration, the snippet is just to illustrate the general problem). There's noboolean
in play anywhere: neither the input or the output of the expression.The text was updated successfully, but these errors were encountered: