This repository has been archived by the owner on Aug 31, 2023. It is now read-only.
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
You can continue the conversation there. Go to discussion →
Note
The teams decided that they prefer to tackle this rules only after #2642 is closed
Description
These are proposed lint rules that come from other sources. They are proposed, they might require a brief discussion for the following reasons:
eslint
, which have a "configuration" per rule. Rome doesn't have a configuration per rule, which means that we might not be able to implement it of we might need to write a default version of that rule, that's why a discussion/decision might be needed;If you want to contribute
ESLint
Enforces comparing
typeof
expressions against valid stringsCan provide auto-fixes if the result of
typeof
is being compared to a well-known constantExample fixes:
typeof a === String
->typeof a === "string"
typeof a === undefined
->typeof a === "undefined"
Enforces dot notation instead of square bracket notation for member access with static names
Example fix:
foo["bar"]
->foo.bar
Disallow else blocks for if statements ending with a return
Example fix:
if (a) { return 1; } else { return 2; }
->if (a) { return 1; } return 2;
Disallow calling
.bind()
on functions that never accessthis
Disallow using single-level deep labelled breaks
Example fix:
label: while(true) { break label; }
->while(true) { break; }
Disallow shorthand type conversions
Example fixes:
!!cond
->Boolean(cond)
+num
->Number(num)
Disallow if statements as the only statement in an else block
Example fix:
if (a) {} else { if (b) {} }
->if (a) {} else if (b) {}
Disallow ternary expressions when a simpler alternative exists
Example fixes:
cond === 4 ? true : false
->cond === 4
value ? value : 4
->value || 4
Enforces labeled statements are referenced by a labelled break
Disallow computed keys with literals in object expressions
Example fix:
{ ["a"]: "b" }
->{ a: "b" }
Disallow aliasing a symbol to the same identifier in object patterns and import / export statements
Example fixes:
const { a: a } = obj;
->const { a } = obj;
import { a as a } from "source";
->import { a } from "source";
export { a as a };
->export { a };
Disallow returning
undefined
as the terminating statement of a functionExample fix:
function foo() { stmt(); return; }
->function foo() { stmt(); }
Enforce shorthand syntax in object expressions
Example fixes:
const obj = { a: a };
->const obj = { a };
const obj = { a: function() {} };
->const obj = { a() {} };
Enforces the use of shorthand operator assignment
Example fix:
a = a + b;
->a += b;
Prefer arrow functions to function expressions
Example fix:
.then(function (res) {})
->.then((res) => {})
Prefer destructuring patterns for array and objects
Example fix:
const a = array[0];
->const [a] = array;
const a = object.a;
->const { a } = object;
Prefer using the exponentiation operator to calling
Math.pow
Example fix:
Math.pow(a, b)
->a ** b
Disallow calling
parseInt
with string literalsExample fixes:
parseInt("23")
->23
parseInt("10111", 2)
->0b10111
parseInt("27", 8)
->0o27
parseInt("17", 16)
->0x17
Prefer
Object.hasOwn()
overObject.prototype.hasOwnProperty.call()
Example fix:
Object.prototype.hasOwnProperty.call(obj, "a")
->Object.hasOwn(obj, "a")
Prefer object spread members to calling
Object.assign
Example fix:
Object.assign({}, foo, { bar: 'baz' })
->{ ..foo, bar: 'baz' }
Disallow calling the RegExp constructor with string literals
Example fix:
new RegExp("abc", "u")
->/abc/u
Enforces literals are in the right hand side of comparison operations
Example fix:
if ("red" === color) {}
->if (color === "red") {}
ESLint Typescript
Disallow the uppercase primitive types
Example fixes:
let foo: String;
->let foo: string;
let foo: Boolean;
->let foo: boolean;
Example errors:
let foo: Function;
let foo: Object;
Disallows non-null assertion in locations that may be confusing
Example fix:
a! == b
->(a!) == b
Disallows the declaration of empty interfaces
Example fixes:
interface Foo {}
->type Foo = {};
interface Bar extends Foo {}
->type Bar = Foo;
Disallows the
any
typeExample error:
const age: any = 'seventeen';
Disallows extra non-null assertion
Example fix:
foo!!!.bar
->foo!.bar
Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean
Example fix:
const a: number = 10;
->const a = 10;
Disallows empty exports that don't change anything in a module file
Example fix:
export const value = 'Hello, world!'; export {};
->export const value = 'Hello, world!';
Enforces the use of
as const
over literal typeExample fix:
let foo = 'bar' as 'bar';
->let foo = 'bar' as const;
Enforces using function types instead of interfaces with call signatures
Example fix:
interface Foo { (): string; }
->type Foo = () => string;
Requires using
namespace
keyword overmodule
keyword to declare custom TypeScript modulesClippy
Checks for nested
if
statements that can be collapsed by combining their conditionsExample fix:
if (a) { if (b) {} }
->if (a && b) {}
Check for comparison operation that could be combined
Example fix:
a == b || a < b
->a <= b
Check for usage of pass-through functions with
flatMap
Example fix:
.flatMap(x => x)
->.flat()
Check for comparisons against plus-one or minus-one operations
Example fix:
a >= b + 1
->a > b
Check for variable declarations that are immediately returned
Example fix:
let a = "value"; return a;
->return "value";
Check for calls to
map
followed by a call toflat
Example fix:
.map(func).flat()
->.flatMap(func)
Check for comparison operation against literals with mismatched case
Example fix:
a.toLowerCase() === "Test"
->.toLowerCase() === "test"
switch(a.toLowerCase()) { case "Test": break; }
->switch(a.toLowerCase()) { case "test": break; }
Check for usage of
forEach
that could be written as for loopsExample fix:
array.forEach(elem => {})
->for(const elem of array) {}
Checks for multiplication by -1 as a form of negation
Example fix:
foo * -1
->-foo
Checks for expressions that could be replaced with optional chaining operations
Example fix:
if(a && a.b) { a.b(); }
->a?.b?.();
Check for closures that just call another function with the same signature
Example fix:
.map(item => foo(item))
->.map(foo)
Search for iterator or string search followed by a comparison to
-1
Example fix:
.indexOf(value) !== -1
->.includes(value)
.findIndex(func) !== -1
->.some(func)
Checks for the use of short circuit boolean conditions as a statement
Example fix:
a() && b();
->if (a()) { b(); }
Checks whether a for loop has a single element
Example fix:
for(const item of [item1]) {}
->const item = item1;
Checks for floating-point operations that can be expressed using built-in functions
Example fixes:
Math.E ** value
->Math.exp(value)
value ** 0.5
->Math.sqrt(value)
value < 0 ? -value : value
->Math.abs(value)
Checks for use of
reduce
when a more succinct alternative existsExample fix:
.reduce((acc, item) => acc || item > 2, false)
->.some(item => item > 2)
.reduce((acc, item) => acc && item > 2, true)
->.every(item => item > 2)
Other Recommended Rules
ESLint
Verify
super()
is called in constructors of derived classes, and not called in constructor of non-derived classes (this rule also tries to check if theextends
reference is a valid class but this is better left to a typechecker)Example errors:
class A extends B { constructor() {} }
class A { constructor() { super(); } }
Check the condition and update of for loops to detect infinite loops
Example error:
for (let i = 0; i < 10; i--) {}
for (let i = 0; i > 10; i++) {}
Enforce that getter functions have a
return
statement on all exit pathsExample error:
const obj = { get prop() {} };
Disallow
async
functions asPromise
executorsExample error:
new Promise(async (resolve, reject) => {})
Disallow assigning to the variable created by a class declaration
Example error:
class A {}; A = 0;
Disallow assignment expression in conditions
Example error:
if(a = "b") {}
Disallow assigning to constant bindings
Example error:
const a = 10; a = 0;
Disallow multiple arguments of the same function from having the same name
Example error:
function (a, b, a) {}
Disallow multiple members of the same class from having the same name
Example error:
class A { foo() {}; foo() {} }
Disallow multiple if statements in the same chain from having the same condition
Example errors:
if (a) {} else if (b) {} else if (a) {}
Disallow multiple members in the same object expression from having the same name
Example error:
const obj = { foo: 'bar', foo: 'baz' };
Disallow multiple case clauses in the same switch statement from having the same condition
Example error:
switch(a) { case 1: break; case 2: break; case 1: break; }
Disallow empty character classes in RegExp literals
Example error:
/abc[]/
Disallow empty destructuring patterns
Example errors:
const {} = object;
const [] = array;
Disallow assigning to the exception binding in a catch clause
Example error:
try {} catch (err) { err = 10; }
Disallow fallthrough between case clauses in switch statements
Example error:
switch (a) { case 1: stmt(); case 2: stmt(); }
Disallow assigning to the variable created by a function declaration
Example error:
function a() {}; a = 0;
Disallow assigning to the binding created by an import
Example error:
import { a } from "source"; a = 0;
Disallow function declarations in nested statements
Example error:
if (a) { function foo() {} }
Disallow all whitespace characters that are not spaces or tabulations
Disallow numeric literals whose value cannot be accurately represented by a double precision float
Example error:
5123000000000000000000000000001
Disallows characters which are made with multiple code points in character class syntax
Example error:
/[❇️]/
Disallows calling the
Symbol
function as a constructorExample error:
new Symbol("foo")
Disallows calling global builtin objects as functions (this might be better suited for a typechecker ?)
Example errors:
Math()
JSON()
Disallow calling methods from
Object.prototype
directly on object instancesExample error:
foo.hasOwnProperty("bar")
Disallow assigning a variable to itself
Example error:
foo = foo;
Disallow returning a value in a setter
Example error:
const obj = { set prop(value) { this._value = value; return value; } };
Disallow using
this
before callingsuper
in a derived classExample error:
class A extends B { constructor() { this.foo = "bar"; super(); } }
Disallow the use of undeclared variables
Disallow code that is statically known to be never reached by control flow
Example error:
function foo() { return; stmt(); }
Disallow control flow statement in
finally
blocksExample error:
try {} finally { return; }
Disallows optional chaining in contexts where
undefined
is not allowed (this might be better suited for a typechecker ?)Example errors:
"key" in obj?.foo
inst instanceof obj?.foo
(obj?.foo)()
(obj?.foo).bar
Disallow unused variables
Disallows useless backreferences in regular expressions
Requires calling
isNaN
when comparing toNaN
Example error:
foo == NaN
ESLint React Hooks
Checks that React Hooks are not called in non-constant control flow
Example error:
function Component({ prop }) { if(prop) { useEffect(); } }
Checks the dependencies array of React Hooks contains all referenced bindings
Example error:
function Component({ prop }) { useEffect(() => { prop(); }, []); }
Clippy
Check for redundant or constant terminals in binary expressions
Example error:
a && b || a
Check for loops that never actually loop
Example error:
while (true) { break; }
Check for loops that never mutate their condition
Example error:
let i = 0; while (i < 10) { stmt(); }
Check for nested min-max calls where the values used for clamping are swapped
Example error:
Math.min(Math.max(value, 1), 0)
Check for constant out-of-bounds indices
Example error:
const array = [1, 2]; array[8];
The text was updated successfully, but these errors were encountered: