angular-tslint-rules: a configuration preset for both TSLint & codelyzer

Burak Tasci
May 4, 2017 · 13 min read

The value of the software produced is directly affected by the quality of the codebase, and not every developer might

  • be aware of the potential pitfalls of certain constructions in TypeScript,
  • be introduced into certain conventions when using the Angular framework,
  • know that not every developer is as capable in understanding an elegant (but abstract) solution as the original developer.

For that purpose, we need to use static code analysis tools such as TSLint and codelyzer to check readability, maintainability, and functionality errors.

Although complying with these tools may seem to appear as undesired overhead or may limit creativity, it becomes easier for any new developers to read, preventing a lot of time/frustration spent figuring out the structure and characteristics of the code.

Containing a set of TSLint and codelyzer rules, angular-tslint-rules has been compiled using many contributions from colleagues, commercial/open-source projects and some other sources from the Internet, as well as years of development using the Angular framework.

Getting started

Installation

You can install angular-tslint-rules using

Note: You should have already installed TSLint and codelyzer.

Usage

To use these TSLint rules, use configuration inheritance via the extends keyword.

A sample configuration is shown below, where `tslint.json` lives adjacent to your `node_modules` folder:

Rules

Class and Member design

  • Do not use classes unless required.
  • Do not specify the keyword (this is the default accessibility level).
  • and members in classes should be denoted with the keyword.
  • Member ordering should be in the following way:

Public members should be ordered before private members.

Static members should be ordered before instance members.

Variables should be ordered before functions.

  • Always prefer readonly private members (maintain immutability).
  • Member overloads should be consecutive.
  • Always prefer unifying any two overloads into one, by using a union or an optional/rest parameter.
  • Always prefer functions over members that do not use .
  • Do not use a class method outside of a method call.
  • Do not use the keyword outside class context (including functions in methods).
  • Do not use in static methods.
  • Do not assign to local variables.
  • Do not use unnecessary constructors.
  • Do not invoke the method twice in a constructor (except in branched statements or nested class constructors).
  • Always prefer parentheses when invoking a constructor via the new keyword.
  • Do not define for classes.
  • Do not use the constructors of , , and .

Interface design

  • Do not define constructors for interfaces.

See: Class and Member design

  • Do not use empty interfaces.
  • Always prefer over in interfaces and types.
  • Always prefer an interface declaration over a type literal ().

Function design

  • Functions should be defined right after the variable declarations.

See: Class and Member design

  • Do not use the built-in function constructor.
  • Do not reassign function parameters (maintain immutability).
  • Do not use void expressions in statement position.
  • Do not use void type outside of generic types of and .
  • Always prefer in void functions and in value-returning functions.
  • Do not invoke within a function, as it makes impossible various performance optimizations.

Anonymous functions

  • Always prefer defining anonymous functions as fat-arrow/lambda functions.
  • fat-arrow/lambda functions should have parenthesis around the function parameters.
  • Always prefer over .
  • Always prefer just over .
  • Do not use unnecessary and/or misleading scope bindings on functions.

Async functions

  • Always prefer marking functions returning a .
  • Do not use the unnecessary (if the awaited value that is not a ).
  • Functions marked must contain an or statement.
  • Do not use the unnecessary .
  • Do not use floating .
  • Do not use for boolean conditions.

Variable design

  • Always prefer keyword where appropriate, for values that should never change.
  • Avoid using (maintain immutability).
  • Do not use the keyword.
  • Do not use implied global variables.
  • Do not define a variable on the global scope from within a smaller scope.
  • Declare one variable at a time (except in loops).
  • Do not use duplicate variable names in the same block scope.
  • Do not use a / statement or destructuring initializer to be initialized to .

Requires and Imports

  • Do not import modules that are not listed as a dependency in the project’s .
  • Do not use import statements with side effect.
  • Always use the statement keywords in alphabetical order.
  • Always use a single statement per module.
  • Do not use statements at all (use ES6-style statement instead).
  • Do not use default imports and exports in ES6-style modules.
  • Do not use statements at all (use ES6-style statement instead).

Types

  • Always prefer defining the return type of functions, methods and property declarations explicitly.
  • Types should be used whenever necessary (no implicit ).
  • Always prefer type inference over explicit type declaration (except for function return types).
  • Do not use the default type arguments explicitly.
  • Meanwhile, avoid type assertion for object literals.
  • Always prefer the use of for type assertions over .
  • Do not use unnecessary type assertions.
  • Always prefer writing an interface or literal type with just a call signature as a function type.
  • Do not use the keyword, always return instead of a reference.
  • Do not use explicitly declared or implicitly returned union types with both and as members.
  • Do not use non-null assertions.
  • Arrays should be defined as instead of .

Objects

  • Always prefer ES6 object spread operator whenever possible.
  • Always prefer ES6 object literal shorthand whenever possible.
  • Always prefer object property names using literals whenever possible.
  • Do not use string literal property access.

Strings

  • Always prefer single-quotes for all strings, and use double-quotes for strings within strings.
  • Always prefer template expressions over string literal concatenation.
  • Do not use string templates outside template strings (``).
  • Always require explicit conversion to string type.

Operators

  • Always prefer using and operators whenever possible.

and operators do type coercion, which can lead to headaches when debugging code.

  • Using comparison operators (, , , ) to compare non-numbers should be avoided.
  • Always prefer explicit and pre-unary operators over and.
  • Always prefer explicit and pre-unary operators over and.
  • Always prefer using operands of the same type with the operator.
  • In a binary expression, a literal should always be on the right-hand side.
  • Do not use the delete operator with dynamic key expressions.
  • Do not use bitwise operators.
  • Always prefer using function to check references.
  • Assignment expressions inside of the condition block of , , and statements should be avoided.

Conditional statements

  • Always prefer conditional expression over a standard statement.
  • Do not compare to two equal variables/literals as operands (ex: or ).
  • Do not compare to a boolean literal (ex: ).
  • Do not use else blocks ending with a , , or statement.
  • Do not use any always truthy/falsy condition in boolean expressions (except right-hand operand or ).

` statement

  • Always prefer loop over a standard loop without initializer, incrementor and/or termination condition.
  • Always prefer loop over a standard loop.
  • Filter statements with an statement (this prevents accidental iteration over properties inherited from an object’s prototype).
  • Do not iterate over an array or keys with a loop.

` statement

  • Each switch statement should have a default case.
  • Each switch case except default should end with , , or .
  • Do not use duplicate switch cases.

` statement

  • Do not use control flow statements, such as , , and in blocks.

Maintainability

  • Use UTF-8 encoding.
  • Limit the level of complexity (cyclomatic complexity) in a function/method by 20 branches.
  • Files should not exceed 400 lines of code.
  • Keep the length of each line under 140 characters.
  • Use 2 spaces for indentation.
  • All files should end in a new line.

Layout

Curly braces

Always use curly braces.

Whitespace

Whitespaces should be used in the following circumstances:

  • All branching statements (///) should be followed by one space.
  • Variable declarations should be separated by one space around the type specification and equals token.
  • There should be one space between the typecast and its target.
  • All operators except the period , left parenthesis , and left bracket should be separated from their operands by one space.
  • There should be no space between the unary/incremental operators and its operand.
  • There should be one space between the type operators , and its operand.
  • There should be one space after the left curly brace and before the right curly brace containing statement keywords.
  • Each separator (,) in the control part of a statement should be followed with one space.
  • There should be no space after the rest/spread operator .
  • The left curly brace followed by a right parenthesis should always separated by one space.
  • For each call signature, index signature, parameter, property declaration and variable declaration;
  • There should be no space between the parameter and the colon indicating the type declaration.
  • There should be one space between the colon and the type declaration.
  • For each function, class member and constructor;
  • There should be no space between the name of the function/member and the left parenthesis of its parameter list.
  • For each fat-arrow/lambda function;
  • There should be one space between the right parenthesis and the .
  • There should be no space within parenthesis.
  • Put one space between the statement keywords.
  • Do not use trailing whitespaces at the end of a line

Empty lines

Empty lines improve code readability by allowing the developer to logically group code blocks.

  • There should be an empty line before the return statement.
  • There should be a separate line for each chained method call.
  • For each function, anonymous function, class member, constructor, , and statements;
  • There should be one space between the right parenthesis and the left curly brace that begins the statement body.
  • For each fat-arrow/lambda function;
  • There should be one space between the and the left curly brace that begins the statement body.
  • statements should indented to align with the line containing the closing brace for the statement.
  • and statements should indented to align with the line containing the closing brace for the statement.
  • Do not use more than one empty line in a row.

Alignment

  • A semicolon should be placed at the end of every simple statement (except at the end of bound class methods).
  • Vertically align elements, members, parameters and statements (helps maintain a readable, consistent style in your codebase.)
  • Do not use trailing commas in array and object literals, destructuring assignments, function typings, named imports/exports and function parameters.

Naming

Classes and Interfaces

  • Files should be in kebab-case.

Classes and Interfaces

  • Class and interface names should be in PascalCase.
  • Interface names should not have an prefix.

Variables and Functions

  • All variable, and function names should be in camelCase.
  • All variables with UPPER_CASE names must be const.
  • Do not use leading and trailing underscore characters.

Documentation

  • Always prefer single-line or JSDoc comments.

Inline Comments

  • Always prefer for all inline comments.
  • There should be one space before the comment.

JSDoc Comments

  • JSDoc comments should start with and end with .
  • Do not use redundant JSDoc comments.
  • Do not use the comments.

Misc

  • Do not use the method (such messages are considered to be for debugging purposes and therefore might ship to the production environment).
  • Do not use the statement (this might cause the environment to stop execution and start up a debugger, if not omitted on the production code).
  • Do not use the function (using on untrusted code might open a program up to several different injection attacks).
  • Do not throw plain strings or concatenations of strings (because only s produce proper stack traces).
  • Do not use namespaces (using is outdated).
  • Do not use internal modules (using is outdated).
  • Always prefer decimal literals beginning with (instead of ).
  • Avoid decimal literals ending with a trailing .
  • Always prefer the parameter to be specified when calling .
  • Do not leave unused expressions in the code.
  • Do not use empty blocks in the code.
  • Do not use missing elements in arrays.
  • Do not use comma operator.

Codelyzer rules

Burak Tasci (fulls1z3)
https://www.linkedin.com/in/buraktasci
http://stackoverflow.com/users/7047325/burak-tasci
https://github.com/fulls1z3

Burak Tasci

In depth articles about software technologies

Burak Tasci

Written by

Full-stack software engineer and enthusiastic power-lifter

Burak Tasci

In depth articles about software technologies

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade