Skip to content

Commit

Permalink
fix(eslint-plugin): [prefer-optional-chain] properly disambiguate bet…
Browse files Browse the repository at this point in the history
…ween `boolean` and `false` (#8685)

* make the example from the docs work

* revert

* allow falsey literals on last operand
  • Loading branch information
abrahamguo committed Mar 25, 2024
1 parent 56358a6 commit 2018f91
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
Expand Up @@ -61,17 +61,13 @@ type Operand = ValidOperand | InvalidOperand;
const NULLISH_FLAGS = ts.TypeFlags.Null | ts.TypeFlags.Undefined;
function isValidFalseBooleanCheckType(
node: TSESTree.Node,
operator: TSESTree.LogicalExpression['operator'],
checkType: 'true' | 'false',
disallowFalseyLiteral: boolean,
parserServices: ParserServicesWithTypeInformation,
options: PreferOptionalChainOptions,
): boolean {
const type = parserServices.getTypeAtLocation(node);
const types = unionTypeParts(type);

const disallowFalseyLiteral =
(operator === '||' && checkType === 'false') ||
(operator === '&&' && checkType === 'true');
if (disallowFalseyLiteral) {
/*
```
Expand Down Expand Up @@ -133,6 +129,7 @@ export function gatherLogicalOperands(
const { operands, newlySeenLogicals } = flattenLogicalOperands(node);

for (const operand of operands) {
const areMoreOperands = operand !== operands.at(-1);
switch (operand.type) {
case AST_NODE_TYPES.BinaryExpression: {
// check for "yoda" style logical: null != x
Expand Down Expand Up @@ -258,8 +255,7 @@ export function gatherLogicalOperands(
operand.operator === '!' &&
isValidFalseBooleanCheckType(
operand.argument,
node.operator,
'false',
areMoreOperands && node.operator === '||',
parserServices,
options,
)
Expand All @@ -285,8 +281,7 @@ export function gatherLogicalOperands(
if (
isValidFalseBooleanCheckType(
operand,
node.operator,
'true',
areMoreOperands && node.operator === '&&',
parserServices,
options,
)
Expand Down
Expand Up @@ -1945,6 +1945,25 @@ describe('hand-crafted cases', () => {
},
],
},
{
code: `
declare const foo: { bar: boolean } | null | undefined;
declare function acceptsBoolean(arg: boolean): void;
acceptsBoolean(foo != null && foo.bar);
`,
output: `
declare const foo: { bar: boolean } | null | undefined;
declare function acceptsBoolean(arg: boolean): void;
acceptsBoolean(foo?.bar);
`,
options: [
{
allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing:
true,
},
],
errors: [{ messageId: 'preferOptionalChain' }],
},
{
code: `
function foo(globalThis?: { Array: Function }) {
Expand Down

0 comments on commit 2018f91

Please sign in to comment.