简体   繁体   中英

Is there an eslint rule to prevent assignment in a single line if statement?

I'm trying to find if there is a non-plugin eslint rule that would allow any of the following:

function(x) {
let count = 0;
  if (doIncrement(x)) count++
  else (doDecrement(x)) count--
  if (count >=10) return "over nine";
  else return "keep counting";
}

But only error on this:

let listOfThings = [];
if (treatAsString) listOfThings[0] = myString.trim();
else listOfThings = [...myString.split(',').map(stringPart => stringPart.trim())];


// or

let name = '';
if (hasFirstAndLAstName) name = `${firstName} ${lastName}`;
else name = `${emailAddress}`;

In favour of using ternary assignment like so:

const listOfThings = treatAsString
  ? [myString.trim()]
  : [...myString.split(',').map(stringPart => stringPart.trim())];

// or

let name = hasFirstAndLAstName ? `${firstName} ${lastName}` : emailAddress;

Does that rule (or a combination of rules) exist for eslint without involving a plug?

There isn't a non-plugin one currently.

In fact, even plugin rules like prefer-ternary won't catch complex cases, such as your fail case that includes indexed field assignment vs full reassignment which I would classify as 'uber-complex'.

With using only base ESLint, you could try the no-restricted-syntax rule . It is not specific but can disallow any syntax you want.

To figure out how you want to configure this rule, check:

  • place your code in a tool that can generate the abstract syntax tree (AST) which will tell you what you want to forbid. The one I used is https://astexplorer.net/
  • the ESLint guide on selectors which outlines how AST selectors can be used and combined. They are very similar to CSS selectors but target programming code.

With these two, here is what I came up with. This is just an example, you might want to adjust the rule further:

no-restricted-syntax: ["error", "IfStatement > ExpressionStatement > AssignmentExpression"]

This will forbid assignments in single-line if statements (and in else ). Note that it does not apply for blocks . Allowed

let x;
if (Math.random() > 0.5) {
    x = 4;
} else {
    x = 2;
}

Disallowed:

let x;
if (Math.random() > 0.5) x = 4;
else x = 2;

For reference, the selector for if statements with a block body that contains an assignment would be IfStatement > BlockStatement > ExpressionStatement > AssignmentExpression

This will only disallow assignments not variable declarations. A construct like const x = 42; falls under VariableDeclaration in AST, so AssignmentExpression is separate and only apply when a variable is already declared.

Try the online ESLint demo with:

/* eslint no-restricted-syntax: ["error", "IfStatement > ExpressionStatement > AssignmentExpression"] */

// allowed
function foo(x) {
  let count = 0;
  if (doIncrement(x)) count++
  else if (doDecrement(x)) count--
  if (count >=10) return "over nine";
  else return "keep counting";
}

// allowed
function foo() {
  const listOfThings = treatAsString
    ? [myString.trim()]
    : [...myString.split(',').map(stringPart => stringPart.trim())];
}

// allowed
function foo() {
  let name = hasFirstAndLAstName ? `${firstName} ${lastName}` : emailAddress;
}

// allowed - assignment is not in `if`
function foo() {
  let x = 1;
  x = 2;
}

// allowed - if statement with blocks
function foo() {
  let x;
  if (Math.random() > 0.5) {
    x = 4;
  } else {
     x = 2;
  }
}

// disallowed
function foo() {
  let listOfThings = [];
  if (treatAsString) listOfThings[0] = myString.trim();
  else listOfThings = [...myString.split(',').map(stringPart => stringPart.trim())];
}

// disallowed
function foo() {
  let name = '';
  if (hasFirstAndLAstName) name = `${firstName} ${lastName}`;
  else name = `${emailAddress}`;
}

// disallowed - single line `if` (even though there is no `else`)
function foo() {
  let x = 1;
  if (Math.random() > 0.5)
    x = 2;
}

Direct link to online ESLint demo

As I said, this is just to showcase the functionality. It does not encourage you into using conditional statements (the error message just amounts to "don't use this") and might also not cover everything you want (eg, assignment in if which is inside another if ). But it is a start.

Still, you might want to look at making a custom plugin that more accurately checks for what you want and reports better errors. The no-restricted-syntax rule is probably too generic for most use cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM