tslint-misc-rules

Collection of miscellaneous TSLint rules

Usage no npm install needed!

<script type="module">
  import tslintMiscRules from 'https://cdn.skypack.dev/tslint-misc-rules';
</script>

README

Build Status npm version PRs Welcome styled with prettier

misc-tslint-rules

Collection of miscellaneous TSLint rules

  1. $ npm install tslint-misc-rules --save-dev
  2. Add the path to it to your tslint.json and add some rules:
{
  "rules": {
    "sort-imports": true
  },
  "rulesDirectory": [
    "tslint-misc-rules"
  ]
}

Rules

  1. sort-imports [has autofix]
  2. prefer-es6-imports
  3. class-method-newlines [has autofix]
  4. jsx-attribute-spacing [has autofix]
  5. jsx-expression-spacing [has autofix]
  6. jsx-no-closing-bracket-newline [has autofix]
  7. jsx-no-braces-for-string-attributes [has autofix]
  8. react-lifecycle-order
  9. prefer-or-operator-over-ternary [has autofix]
  10. no-property-initializers
  11. camel-case-local-function
  12. declare-class-methods-after-use
  13. no-braces-for-single-line-arrow-functions [has autofix]
  14. no-unnecessary-parens-for-arrow-function-arguments

"sort-imports"

Fails:

import b from "b";
import a from "a";

Passes:

import a from "a";
import b from "b";

Blocks are grouped, so this also passes:

import a from "a";
import z from "z";
testSetup();
import c from "c";
import d from "d";

Precedence is essentially *, {, then alpha, so:

import * as a from "a";
import { b, c } from "bc";
import d from "d";

This rule has one option, whitespace-insensitive, that collapses all whitespace spans (including line breaks) down to one space when sorting. This provides compatibility with formatters like Prettier, which may decide to turn a single-line import into a multi-line import when it grows too long. This could otherwise introduce a lint failure. Ex:

"sort-imports": [ true, "whitespace-insensitive" ]

Fails:

import {
  x,
  y,
} from "xy";
import { a } from "a";

Passes:

import { a } from "a";
import {
  x,
  y,
} from "xy";

"prefer-es6-imports"

With configuration (required):

{
  "prefer-es6-imports": [
    true,
    "module-name"
  ]
}

Fails:

import mod = require("module-name");
import mod = require("path/to/module-name");
import mod = require("../module-name");

"class-method-newlines"

Ensure each method in class is preceded by a newline.

Fails:

class foo {
    propertyOne: any;
    propertyTwo: any;
    one() {
    }
    two() {
    }
}

Passes:

class foo {
    propertyOne: any;
    propertyTwo: any;

    one() {
    }

    two() {
    }
}

The first method is exempt, so this also passes:

class foo {
    one() {
    }

    two() {
    }
}

"jsx-attribute-spacing"

Fails:

<div prop = { value }/>
<div prop= { value }/>
<div prop ={ value }/>

Passes:

<div prop={ value }/>

"jsx-expression-spacing"

Fails:

<div prop={value}/>
<div prop={ value}/>
<div prop={value }/>
<div>
  {value}
  { value}
  {value }
</div>

Passes:

<div prop={ value }/>
<div>
  { value }
</div>

"jsx-no-closing-bracket-newline"

Fails:

  <a className="asdf"
      href="/foo"
  />

  <div
      className="qwer"
      name="asdf"
  >
      text
  </div>

Passes:

  <a className="asdf"
      href="/foo" />

  <div
      className="qwer"
      name="asdf">
      text
  </div>

"jsx-no-braces-for-string-attributes"

Fails:

<div prop={ "value" }/>

Passes:

<div prop="value"/>

"react-lifecycle-order"

With configuration (optional):

{
  "react-lifecycle-order": [
    true,
    "componentWillMount",
    "render",
    "componentWillUnmount"
  ]
}

Fails:

class extends React.Component {
    componentWillMount() {
    }

    componentWillUnmount() {
    }

    render() {
    }
}

Passes:

class extends React.Component {
    componentWillMount() {
    }

    render() {
    }

    componentWillUnmount() {
    }
}

If configuration is not specified, React's invocation order is used.

"prefer-or-operator-over-ternary"

Fails:

const maybeFoo = foo ? foo : bar;

Passes:

const maybeFoo = foo || bar;

"no-property-initializers"

Fails:

class foo {
  bar = 42;
}

Passes:

class foo {
  bar: number;
}

"camel-case-local-functions"

Due to React's Stateless Functional Components, this rule checks callsites rather than declarations.
Fails:

import FooImport from 'foo';

function FooDeclaration() { }

FooImport();
FooDeclaration();

Passes:

import fooImport from 'foo';

function fooDeclaration() { }
function SomeSFC(props) { return null; }

fooImport();
fooDeclaration();
const el = </SomeSFC>;

"declare-class-methods-after-use"

Fails:

class foo {
    bar() {
    }

    foo() {
      this.bar();
    }
}

Passes:

class foo {
    foo() {
      this.bar();
    }

    bar() {
    }
}

"no-braces-for-single-line-arrow-functions"

Fails:

const add = (x, y) => { return x + y };
const btn = <button onClick={ e => { console.log(e); } } />;

Passes:

const add = (x, y) => x + y;
const btn = <button onClick={ e => console.log(e) } />;

"no-unnecessary-parens-for-arrow-function-arguments"

Fails:

const log = (x) => console.log(x);

Passes:

const log = x => console.log(x);