Thursday 11 October 2018

Introduction to TSLint

UPDATE: TSLint has been deprecated as of 2019. typescript-eslint is now the best option for linting TypeScript.

---

TSLint is a TypeScript linter.

Source code of the project which uses TSLint is on GitHub.

Installation

Let's install it as a development dependency:

..\demo-typescript>npm install tslint --save-dev
+ tslint@5.11.0
added 40 packages from 20 contributors and audited 51 packages in 5.225s
found 0 vulnerabilities

CLI Usage

Let's run tslint with no arguments specified, from the project's root directory:

..\demo-typescript>npx tslint
No files specified. Use --project to lint a project folder.

Let's find what is --project argument and see what are the other command line arguments:

..\demo-typescript>npx tslint --help
Usage:  [options]

Options:
  -v, --version                          output the version number
  -c, --config [config]                  configuration file
  -e, --exclude <exclude>                exclude globs from path expansion (default: [])
  --fix                                  fixes linting errors for select rules (this may overwrite linted files)
  --force                                return status code 0 even if there are lint errors
  -i, --init                             generate a tslint.json config file in the current working directory
  -o, --out [out]                        output file
  --outputAbsolutePaths                  whether or not outputted file paths are absolute
  -r, --rules-dir [rules-dir]            rules directory
  -s, --formatters-dir [formatters-dir]  formatters directory
  -t, --format [format]                  output format (prose, json, stylish, verbose, pmd, msbuild, checkstyle, vso, fileslist, codeFrame)
  --test                                 test that tslint produces the correct output for the specified directory
  -p, --project [project]                tsconfig.json file
  --type-check                           (deprecated) check for type errors before linting the project
  -h, --help                             output usage information
tslint accepts the following commandline options:

    -c, --config:
        The location of the configuration file that tslint will use to
        determine which rules are activated and what options to provide
        to the rules. If no option is specified, the config file named
        tslint.json is used, so long as it exists in the path.
        The format of the file is { rules: { /* rules list */ } },
        where /* rules list */ is a key: value comma-separated list of
        rulename: rule-options pairs. Rule-options can be either a
        boolean true/false value denoting whether the rule is used or not,
        or a list [boolean, ...] where the boolean provides the same role
        as in the non-list case, and the rest of the list are options passed
        to the rule that will determine what it checks for (such as number
        of characters for the max-line-length rule, or what functions to ban
        for the ban rule).

    -e, --exclude:
        A filename or glob which indicates files to exclude from linting.
        This option can be supplied multiple times if you need multiple
        globs to indicate which files to exclude.

    --fix:
        Fixes linting errors for select rules. This may overwrite linted files.

    --force:
        Return status code 0 even if there are any lint errors.
        Useful while running as npm script.

    -i, --init:
        Generates a tslint.json config file in the current working directory.

    -o, --out:
        A filename to output the results to. By default, tslint outputs to
        stdout, which is usually the console where you're running it from.

    --outputAbsolutePaths:
        If true, all paths in the output will be absolute.

    -r, --rules-dir:
        An additional rules directory, for user-created rules.
        tslint will always check its default rules directory, in
        node_modules/tslint/lib/rules, before checking the user-provided
        rules directory, so rules in the user-provided rules directory
        with the same name as the base rules will not be loaded.

    -s, --formatters-dir:
        An additional formatters directory, for user-created formatters.
        Formatters are files that will format the tslint output, before
        writing it to stdout or the file passed in --out. The default
        directory, node_modules/tslint/build/formatters, will always be
        checked first, so user-created formatters with the same names
        as the base formatters will not be loaded.

    -t, --format:
        The formatter to use to format the results of the linter before
        outputting it to stdout or the file passed in --out. The core
        formatters are prose (human readable), json (machine readable)
        and verbose. prose is the default if this option is not used.
        Other built-in options include pmd, msbuild, checkstyle, and vso.
        Additional formatters can be added and used if the --formatters-dir
        option is set.

    --test:
        Runs tslint on matched directories and checks if tslint outputs
        match the expected output in .lint files. Automatically loads the
        tslint.json files in the directories as the configuration file for
        the tests. See the full tslint documentation for more details on how
        this can be used to test custom rules.

    -p, --project:
        The path to the tsconfig.json file or to the directory containing
        the tsconfig.json file. The file will be used to determine which
        files will be linted. This flag also enables rules that require the
        type checker.

    --type-check:
        (deprecated) Checks for type errors before linting a project.
        --project must be specified in order to enable type checking.

    -v, --version:
        The current version of tslint.

    -h, --help:
        Prints this help message.

Let's specify path to tsconfig.json file (which is in the project's root where we're executing tsling from):

..\demo-typescript>npx tslint --project ./
no-unused-variable is deprecated. Since TypeScript 2.9. Please use the built-in compiler checks instead.

Could not find implementations for the following rules specified in the configuration:
    label-undefined
    no-duplicate-key
    no-trailing-comma
    no-unreachable
    use-strict
Try upgrading TSLint and/or ensuring that you have all necessary custom rules installed.
If TSLint was recently upgraded, you may have old rules configured which need to be cleaned up.


ERROR: C:/dev/github/demo-typescript/src/index.ts[3, 5]: expected variable-declaration: 'dayTimeGreetingGenerator' to have a typedef
ERROR: C:/dev/github/demo-typescript/src/index.ts[5, 10]: expected call-signature: 'createPersonalGreeting' to have a typedef
ERROR: C:/dev/github/demo-typescript/src/index.ts[9, 5]: expected variable-declaration: 'user' to have a typedef
ERROR: C:/dev/github/demo-typescript/src/index.ts[12, 5]: expected variable-declaration: 'greeting' to have a typedef
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[2, 19]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[3, 21]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[4, 19]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[1, 57]: trailing whitespace
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[5, 25]: expected nospace before colon in call-signature
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[7, 33]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[1, 18]: interface name must start with a capitalized I
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[2, 18]: expected nospace before colon in call-signature

Good, linting works!

Configuration


If we run:

..\demo-typescript>npx tslint --init

...tslint creates TSLint configuration file - tslint.json in the current directory.  tslint.json for now only has its default content:

{
    "defaultSeverity": "error",
    "extends": [
        "tslint:recommended"
    ],
    "jsRules": {},
    "rules": {},
    "rulesDirectory": []
}

After having TSLint config file, its output contains only linting messages:

..\demo-typescript>npx tslint --project ./

ERROR: C:/dev/github/demo-typescript/src/index.ts[3, 5]: Identifier 'dayTimeGreetingGenerator' is never reassigned; use 'const' instead of 'let'.
ERROR: C:/dev/github/demo-typescript/src/index.ts[5, 39]: expected nospace before colon in parameter
ERROR: C:/dev/github/demo-typescript/src/index.ts[9, 5]: Identifier 'user' is never reassigned; use 'const' instead of 'let'.
ERROR: C:/dev/github/demo-typescript/src/index.ts[12, 5]: Identifier 'greeting' is never reassigned; use 'const' instead of 'let'.
ERROR: C:/dev/github/demo-typescript/src/index.ts[14, 1]: Calls to 'console.log' are not allowed.
ERROR: C:/dev/github/demo-typescript/src/index.ts[14, 23]: file should end with a newline
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[2, 19]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[3, 21]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[4, 19]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[4, 33]: Missing trailing comma
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[5, 2]: file should end with a newline
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[1, 57]: trailing whitespace
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[2, 1]: Import sources within a group must be alphabetized.
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[5, 25]: expected nospace before colon in call-signature
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[6, 20]: expected nospace before colon in variable-declaration
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[7, 21]: expected nospace before colon in variable-declaration
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[7, 33]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[8, 21]: missing whitespace
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[17, 3]: file should end with a newline
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[1, 18]: interface name must start with a capitalized I
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[2, 18]: expected nospace before colon in call-signature
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[3, 2]: file should end with a newline


We can now add linting to TS build task in package.json. TSLint documentation says "Please ensure that the TypeScript source files compile correctly before running the linter." and we'll place linting after transpilation:

"build-ts": "tsc && tslint -p ./",

If we run npm task we'll see that TSLint process exited with error code:

..\demo-typescript>npm run build-ts

> demo-typescript@1.0.0 build-ts C:\dev\github\demo-typescript
> tsc && tslint -p ./


ERROR: C:/dev/github/demo-typescript/src/index.ts[3, 5]: Identifier 'dayTimeGreetingGenerator' is never reassigned; use 'const' instead of 'let'.
ERROR: C:/dev/github/demo-typescript/src/index.ts[5, 39]: expected nospace before colon in parameter
ERROR: C:/dev/github/demo-typescript/src/index.ts[9, 5]: Identifier 'user' is never reassigned; use 'const' instead of 'let'.
ERROR: C:/dev/github/demo-typescript/src/index.ts[12, 5]: Identifier 'greeting' is never reassigned; use 'const' instead of 'let'.
ERROR: C:/dev/github/demo-typescript/src/index.ts[14, 1]: Calls to 'console.log' are not allowed.
ERROR: C:/dev/github/demo-typescript/src/index.ts[14, 23]: file should end with a newline
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[2, 19]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[3, 21]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[4, 19]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[4, 33]: Missing trailing comma
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreeting.ts[5, 2]: file should end with a newline
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[1, 57]: trailing whitespace
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[2, 1]: Import sources within a group must be alphabetized.
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[5, 25]: expected nospace before colon in call-signature
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[6, 20]: expected nospace before colon in variable-declaration
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[7, 21]: expected nospace before colon in variable-declaration
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[7, 33]: ' should be "
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[8, 21]: missing whitespace
ERROR: C:/dev/github/demo-typescript/src/module/dayTimeGreetingGenerator.ts[17, 3]: file should end with a newline
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[1, 18]: interface name must start with a capitalized I
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[2, 18]: expected nospace before colon in call-signature
ERROR: C:/dev/github/demo-typescript/src/module/greetingGenerator.ts[3, 2]: file should end with a newline

npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! demo-typescript@1.0.0 build-ts: `tsc && tslint -p ./`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the demo-typescript@1.0.0 build-ts script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\komazec\AppData\Roaming\npm-cache\_logs\2018-10-11T16_35_49_031Z-debug.log

Having TSLint exit with Exit status 2 is expected as TSLint reported suggestions with ERROR severity and its documentation says that status 2 indeed means "Linting failed with one or more rule violations with severity error".

We can see that linter complaints about using single quotation marks instead of double ones (' should be "). TS coding conventions actually prefers single quotes so we want to change the rule for TSLinter. The rule we want to change in tslint.json is quotemark:

    ...
    "rules": {
        "quotemark": [true, "single"]
    },
    ...

If we run tslint again, we'll see that it does not emit ' should be " messages anymore.

VSCode Extension

TSLint

It will start showing errors/suggestions as soon as plugin is installed and VSCode reloaded.

Disabling TSLint Errors


To disable some error in the next line only:

E.g. for some line I got the following error:

Expected a 'for-of' loop instead of a 'for' loop with this simple iteration (prefer-for-of) tslint(1)

To disable that error the following line should be added before that code line:

// tslint:disable-next-line:prefer-for-of

TSLint rule flags

References:


https://palantir.github.io/tslint/
tslint says calls to console.log are not allowed - How do I allow this?

No comments: