Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

tslint-immutable

jonaskello17.4kMITdeprecated6.0.1

Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

TSLint rules to disable mutation in TypeScript.

tslint, immutability

readme

tslint-immutable

npm version travis build Coverage Status code style: prettier MIT license

TSLint rules to disable mutation in TypeScript.

:warning: TSLint will be deprecated some time in 2019. See this issue for more details: Roadmap: TSLint → ESLint.

:rocket: Work has started to port these rules to a new eslint plugin over at the eslint-plugin-ts-immutable repo. Please head over there and give it a :star: :-).

Background

In some applications it is important to not mutate any data, for example when using Redux to store state in a React application. Moreover immutable data structures has a lot of advantages in general so I want to use them everywhere in my applications.

I originally used immutablejs for this purpose. It is a really nice library but I found it had some drawbacks. Specifically when debugging it was hard to see the structure, creating JSON was not straightforward, and passing parameters to other libraries required converting to regular mutable arrays and objects. The seamless-immutable project seems to have the same conclusions and they use regular objects and arrays and check for immutability at run-time. This solves all the aformentioned drawbacks but introduces a new drawback of only being enforced at run-time. (Altough you loose the structural sharing feature of immutablejs with this solution so you would have to consider if that is something you need).

Then typescript 2.0 came along and introduced readonly options for properties, indexers and arrays. This enables us to use regular object and arrays and have the immutability enfored at compile time instead of run-time. Now the only drawback is that there is nothing enforcing the use of readonly in typescript.

This can be solved by using linting rules. So the aim of this project is to leverage the type system in typescript to enforce immutability at compile-time while still using regular objects and arrays.

Installing

npm install tslint-immutable --save-dev

See the example tslint.json file for configuration.

Compability

  • tslint-immutable 5.x.x requires typescript >=2.8, node >=6, and tslint 5.x.x.
  • tslint-immutable 3.x.x requires tslint 5.x.x.
  • tslint-immutable 2.x.x requires tslint 4.x.x.
  • tslint-immutable 1.x.x requires tslint 3.x.x.

TSLint Rules

In addition to immutable rules this project also contains a few rules for enforcing a functional style of programming. The following rules are available:

Immutability rules

readonly-keyword

This rule enforces use of the readonly modifier. The readonly modifier can appear on property signatures in interfaces, property declarations in classes, and index signatures.

Below is some information about the readonly modifier and the benefits of using it:

You might think that using const would eliminate mutation from your TypeScript code. Wrong. Turns out that there's a pretty big loophole in const.

interface Point {
  x: number;
  y: number;
}
const point: Point = { x: 23, y: 44 };
point.x = 99; // This is legal

This is why the readonly modifier exists. It prevents you from assigning a value to the result of a member expression.

interface Point {
  readonly x: number;
  readonly y: number;
}
const point: Point = { x: 23, y: 44 };
point.x = 99; // <- No object mutation allowed.

This is just as effective as using Object.freeze() to prevent mutations in your Redux reducers. However the readonly modifier has no run-time cost, and is enforced at compile time. A good alternative to object mutation is to use the ES2016 object spread syntax that was added in typescript 2.1:

interface Point {
  readonly x: number;
  readonly y: number;
}
const point: Point = { x: 23, y: 44 };
const transformedPoint = { ...point, x: 99 };

Note that you can also use object spread when destructuring to delete keys in an object:

let { [action.id]: deletedItem, ...rest } = state;

The readonly modifier also works on indexers:

const foo: { readonly [key: string]: number } = { a: 1, b: 2 };
foo["a"] = 3; // Error: Index signature only permits reading

Has Fixer

Yes

Options

Example config

"readonly-keyword": true
"readonly-keyword": [true, "ignore-local"]
"readonly-keyword": [true, "ignore-local", {"ignore-prefix": "mutable"}]

readonly-array

This rule enforces use of ReadonlyArray<T> or readonly T[] instead of Array<T> or T[].

Below is some information about the ReadonlyArray<T> type and the benefits of using it:

Even if an array is declared with const it is still possible to mutate the contents of the array.

interface Point {
  readonly x: number;
  readonly y: number;
}
const points: Array<Point> = [{ x: 23, y: 44 }];
points.push({ x: 1, y: 2 }); // This is legal

Using the ReadonlyArray<T> type or readonly T[] will stop this mutation:

interface Point {
  readonly x: number;
  readonly y: number;
}

const points: ReadonlyArray<Point> = [{ x: 23, y: 44 }];
// const points: readonly Point[] = [{ x: 23, y: 44 }]; // This is the alternative syntax for the line above

points.push({ x: 1, y: 2 }); // Unresolved method push()

Has Fixer

Yes

Options

Example config

"readonly-array": true
"readonly-array": [true, "ignore-local"]
"readonly-array": [true, "ignore-local", {"ignore-prefix": "mutable"}]

no-let

This rule should be combined with tslint's built-in no-var-keyword rule to enforce that all variables are declared as const.

There's no reason to use let in a Redux/React application, because all your state is managed by either Redux or React. Use const instead, and avoid state bugs altogether.

let x = 5; // <- Unexpected let or var, use const.

What about for loops? Loops can be replaced with the Array methods like map, filter, and so on. If you find the built-in JS Array methods lacking, use ramda, or lodash-fp.

const SearchResults = ({ results }) => (
  <ul>
    {results.map(result => (
      <li>result</li>
    )) // <- Who needs let?
    }
  </ul>
);

Has Fixer

Yes

Options

Example config

"no-let": true
"no-let": [true, "ignore-local"]
"no-let": [true, "ignore-local", {"ignore-prefix": "mutable"}]

no-array-mutation

Type Info Required

This rule prohibits mutating an array via assignment to or deletion of their elements/properties. This rule enforces array immutability without the use of ReadonlyArray<T> (as apposed to readonly-array).

const x = [0, 1, 2];

x[0] = 4; // <- Mutating an array is not allowed.
x.length = 1; // <- Mutating an array is not allowed.
x.push(3); // <- Mutating an array is not allowed.

Has Fixer

No

Options

Example config

"no-array-mutation": true
"no-array-mutation": [true, {"ignore-prefix": "mutable"}]
"no-array-mutation": [true, "ignore-new-array"]

no-object-mutation

Type Info Required

This rule prohibits syntax that mutates existing objects via assignment to or deletion of their properties. While requiring the readonly modifier forces declared types to be immutable, it won't stop assignment into or modification of untyped objects or external types declared under different rules. Forbidding forms like a.b = 'c' is one way to plug this hole. Inspired by the no-mutation rule of eslint-plugin-immutable.

const x = { a: 1 };

x.foo = "bar"; // <- Modifying properties of existing object not allowed.
x.a += 1; // <- Modifying properties of existing object not allowed.
delete x.a; // <- Modifying properties of existing object not allowed.
Object.assign(x, { b: 2 }); // <- Modifying properties of existing object not allowed.

Has Fixer

No

Options

Example config

"no-object-mutation": true
"no-object-mutation": [true, {"ignore-prefix": "mutable"}]

no-method-signature

There are two ways function members can be declared in an interface or type alias:

interface Zoo {
  foo(): string; // MethodSignature, cannot have readonly modifier
  readonly bar: () => string; // PropertySignature
}

The MethodSignature and the PropertySignature forms seem equivalent, but only the PropertySignature form can have a readonly modifier. Becuase of this any MethodSignature will be mutable. Therefore the no-method-signature rule disallows usage of this form and instead proposes to use the PropertySignature which can have a readonly modifier. It should be noted however that the PropertySignature form for declaring functions does not support overloading.

no-delete

The delete operator allows for mutating objects by deleting keys. This rule disallows any delete expressions.

delete object.property; // Unexpected delete, objects should be considered immutable.

As an alternative the spread operator can be used to delete a key in an object (as noted here):

const { [action.id]: deletedItem, ...rest } = state;

Functional style rules

no-this, no-class

Thanks to libraries like recompose and Redux's React Container components, there's not much reason to build Components using React.createClass or ES6 classes anymore. The no-this rule makes this explicit.

const Message = React.createClass({
  render: function() {
    return <div>{this.props.message}</div>; // <- no this allowed
  }
});

Instead of creating classes, you should use React 0.14's Stateless Functional Components and save yourself some keystrokes:

const Message = ({ message }) => <div>{message}</div>;

What about lifecycle methods like shouldComponentUpdate? We can use the recompose library to apply these optimizations to your Stateless Functional Components. The recompose library relies on the fact that your Redux state is immutable to efficiently implement shouldComponentUpdate for you.

import { pure, onlyUpdateForKeys } from "recompose";

const Message = ({ message }) => <div>{message}</div>;

// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedMessage = pure(Message);

// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedMessage = onlyUpdateForKeys(["message"], Message);

no-mixed-interface

Mixing functions and data properties in the same interface is a sign of object-orientation style. This rule enforces that an inteface only has one type of members, eg. only data properties or only functions.

no-expression-statement

When you call a function and don’t use it’s return value, chances are high that it is being called for its side effect. e.g.

array.push(1);
alert("Hello world!");

This rule checks that the value of an expression is assigned to a variable and thus helps promote side-effect free (pure) functions.

Options

Example config

"no-expression-statement": true
"no-expression-statement": [true, {"ignore-prefix": "console."}]
"no-expression-statement": [true, {"ignore-prefix": ["console.log", "console.error"]}]

no-if-statement

If statements is not a good fit for functional style programming as they are not expresssions and do not return a value. This rule disallows if statements.

let x;
if (i === 1) {
  x = 2;
} else {
  x = 3;
}

Instead consider using the tenary operator which is an expression that returns a value:

const x = i === 1 ? 2 : 3;

For more background see this blog post and discussion in #54.

no-loop-statement

In functional programming we want everthing to be an expression that returns a value. Loops in typescript are statements so they are not a good fit for a functional programming style. This rule disallows for loop statements, including for, for...of, for...in, while, and do...while.

const numbers = [1, 2, 3];
const double = [];
for (let i = 0; i < numbers.length; i++) {
  double[i] = numbers[i] * 2;
}

Instead consider using map or reduce:

const numbers = [1, 2, 3];
const double = numbers.map(n => n * 2);

For more background see this blog post and discussion in #54.

no-throw

Exceptions are not part of functional programming.

throw new Error("Something went wrong."); // Unexpected throw, throwing exceptions is not functional.

As an alternative a function should return an error:

function divide(x: number, y: number): number | Error {
  return y === 0 ? new Error("Cannot divide by zero.") : x / y;
}

Or in the case of an async function, a rejected promise should be returned.

async function divide(x: Promise<number>, y: Promise<number>): Promise<number> {
  const [xv, yv] = await Promise.all([x, y]);

  return yv === 0
    ? Promise.reject(new Error("Cannot divide by zero."))
    : xv / yv;
}

no-try

Try statements are not part of functional programming. See no-throw for more information.

no-reject

You can view a Promise as a result object with built-in error (something like { value: number } | { error: Error }) in which case a rejected Promise can be viewed as a returned result and thus fits with functional programming. You can also view a rejected promise as something similar to an exception and as such something that does not fit with functional programming. If your view is the latter you can use the no-reject rule to disallow rejected promises.

async function divide(
  x: Promise<number>,
  y: Promise<number>
): Promise<number | Error> {
  const [xv, yv] = await Promise.all([x, y]);

  // Rejecting the promise is not allowed so resolve to an Error instead

  // return yv === 0
  //   ? Promise.reject(new Error("Cannot divide by zero."))
  //   : xv / yv;

  return yv === 0 ? new Error("Cannot divide by zero.") : xv / yv;
}

Options

Using the ignore-local option

If a tree falls in the woods, does it make a sound? If a pure function mutates some local data in order to produce an immutable return value, is that ok?

The quote above is from the clojure docs. In general, it is more important to enforce immutability for state that is passed in and out of functions than for local state used for internal calculations within a function. For example in Redux, the state going in and out of reducers needs to be immutable while the reducer may be allowed to mutate local state in its calculations in order to achieve higher performance. This is what the ignore-local option enables. With this option enabled immutability will be enforced everywhere but in local state. Function parameters and return types are not considered local state so they will still be checked.

Note that using this option can lead to more imperative code in functions so use with care!

Using the ignore-class option

Doesn't check for readonly in classes.

Using the ignore-interface option

Doesn't check for readonly in interfaces.

Using the ignore-rest-parameters option

Doesn't check for ReadonlyArray for function rest parameters.

Using the ignore-return-type option

Doesn't check the return type of functions.

Using the ignore-prefix option

Some languages are immutable by default but allows you to explicitly declare mutable variables. For example in reason you can declare mutable record fields like this:

type person = {
  name: string,
  mutable age: int
};

Typescript is not immutable by default but it can be if you use this package. So in order to create an escape hatch similar to how it is done in reason the ignore-prefix option can be used. For example if you configure it to ignore variables with names that has the prefix "mutable" you can emulate the above example in typescript like this:

type person = {
  readonly name: string;
  mutableAge: number; // This is OK with ignore-prefix = "mutable"
};

Yes, variable names like mutableAge are ugly, but then again mutation is an ugly business :-).

Using the ignore-suffix option

Like ignore-prefix but with suffix matching instead of prefix matching.

Using the ignore-pattern option

Like ignore-prefix and ignore-suffix but with more control.

This option allows you to specify dot seperated paths what should be ignored.

For example, the following config would ignore all object mutations for all properties that start with "mutable".

{
  "no-object-mutation": [true, { "ignore-pattern": "**.mutable*" }]
}

The following wildcards can be used when specifing a pattern:

  • ** - Match any depth (including zero). Can only be used as a full accessor.
  • * - When used as a full accessor, match the next accessor. When used as part of an accessor, match any characters.

Using the ignore-prefix option with no-expression-statement

Expression statements typically cause side effects, however not all side effects are undesirable. One example of a helpful side effect is logging. To not get warning of every log statement, we can configure the linter to ignore well known expression statement prefixes.

One such prefix could be console., which would cover both these cases:

const doSomething(arg:string) => {
  if (arg) {
    console.log("Argument is", arg);
  } else {
    console.warn("Argument is empty!");
  }
  return `Hello ${arg}`;
}

Using the ignore-new-array option with no-array-mutation

This option allows for the use of array mutator methods to be chained to newly created arrays.

For example, an array can be immutably sorted like so:

const original = ["foo", "bar", "baz"];
const sorted = original.slice().sort((a, b) => a.localeCompare(b)); // This is OK with ignore-new-array - note the use of the `slice` method which returns a copy of the original array.

no-var-keyword

Without this rule, it is still possible to create var variables that are mutable.

no-parameter-reassignment

Without this rule, function parameters are mutable.

typedef with call-signature option

For performance reasons, tslint-immutable does not check implicit return types. So for example this function will return an mutable array but will not be detected (see #18 for more info):

function foo() {
  return [1, 2, 3];
}

To avoid this situation you can enable the built in typedef rule like this:

"typedef": [true, "call-signature"]

Now the above function is forced to declare the return type becomes this and will be detected.

Sample Configuration File

Here's a sample TSLint configuration file (tslint.json) that activates all the rules:

{
  "extends": ["tslint-immutable"],
  "rules": {

    // Recommended built-in rules
    "no-var-keyword": true,
    "no-parameter-reassignment": true,
    "typedef": [true, "call-signature"],

    // Immutability rules
    "readonly-keyword": true,
    "readonly-array": true,
    "no-let": true,
    "no-object-mutation": true,
    "no-delete": true,
    "no-method-signature": true,

    // Functional style rules
    "no-this": true,
    "no-class": true,
    "no-mixed-interface": true,
    "no-expression-statement": true,
    "no-if-statement": true

  }
}

It is also possible to enable all the rules in tslint-immutable by extending tslint-immutable/all like this:

{
  "extends": ["tslint-immutable/all"]
}

How to contribute

For new features file an issue. For bugs, file an issue and optionally file a PR with a failing test. Tests are really easy to do, you just have to edit the *.ts.lint files under the test directory. Read more here about tslint testing.

How to develop

To execute the tests first run yarn build and then run yarn test.

While working on the code you can run yarn test:work. This script also builds before running the tests. To run a subset of the tests, change the path for yarn test:work in package.json.

Please review the tslint performance tips in order to write rules that run efficiently at run-time. For example, note that using SyntaxWalker or any subclass thereof like RuleWalker is inefficient. Note that tslint requires the use of class as an entrypoint, but you can make a very small class that inherits from AbstractRule which directly calls this.applyWithFunction and from there you can switch to using a more functional programming style.

In order to know which AST nodes are created for a snippet of typescript code you can use ast explorer.

How to publish

yarn version --patch
yarn version --minor
yarn version --major

Prior work

This work was originally inspired by eslint-plugin-immutable.

changelog

Change Log

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

Unreleased

[v6.0.1] - 2019-07-02

Added

  • Deprecation notice added to the readme.

[v6.0.0] - 2019-06-05

  • Overhaul ignore-prefix, adding in ignore-suffix and ignore-pattern. See PR #137
  • Updated the list of rules included in each ruleset. See PR #138

[v5.5.2] - 2019-03-25

  • readonly-array rule with the option ignore-prefix set will now ignore nested arrays within an ignored variable. See #132. See PR #133

[v5.5.1] - 2019-03-22

  • no-array-mutation now checks nested arrays. See #134. See PR #135

[v5.5.0] - 2019-03-21

  • readonly-array rule now allows for the readonly keyword to specify an array as readonly. This is a new feature supported in TypeScript 3.4. See #129. See PR #130

[v5.4.0] - 2019-03-14

  • no-object-mutation rule now disallows Object.assign mutation on identifiers and property access expressions. See #112. See PR #127

[v5.3.3] - 2019-03-12

  • Fixed rule readonly-array with option ignore-return-type not checking within union, intersection and conditional types. This fix should now catch all return types that contain a nested array. See #124. See PR #125

[v5.3.2] - 2019-03-07

Fixed

  • Fixed rule readonly-array with option ignore-return-type not checking within tuple types. See #121. See PR #122

[v5.3.1] - 2019-03-07

Fixed

  • Fixed rule readonly-array with option ignore-return-type not checking within generic parameters. See #117. Thanks to @RebeccaStevens for this fix! (See PR #120).

v5.3.0 - 2019-02-19

Added

  • New rule no-reject (moved from no-throw rule in previous version). See PR #118.

v5.2.0 - 2019-02-14

Added

  • Update no-throw to not allow Promise.reject(). See #115 and PR #116. Thanks to @sbdchd for this addition!

v5.1.2 - 2019-01-25

  • Republished without changes (becuase previous publish failed).

v5.1.1 - 2019-01-25

Fixed

  • Fixes readonly-keyword fixer adds the readonly modifier in the wrong place for decorated class properties. See #81. Thanks to @tkryskiewicz for this fix! (See PR #113).

v5.1.0 - 2019-01-15

Added

  • New option ignore-new-array for the no-array-mutation rule. This option replaces the ignore-mutation-following-accessor option, however the old option name will remain as an alias and will be removed in the next major release. See #102. Thanks to @RebeccaStevens for adding this option! (See PR #110)

v5.0.1 - 2018-12-15

Fixed

  • Fixed a regression in the readonly-array. See #104.

v5.0.0 - 2018-11-24

Changed

  • Internal refactoring to use the tsutils library, see PR 100. This cleans up a lot of code and makes it easier to do further development. Becasue the tsutils library requires typescript version >=2.8 and node >=6 this refactoring required a major version bump. Big thanks to RebeccaStevens for the amazing work on this refactoring :-).

v4.9.1 - 2018-11-04

Fixed

  • ignore-return-type option for the readonly-array doesn't catch method declarations. See #95.

v4.9.0 - 2018-11-01

Added

  • New option ignore-return-type for the readonly-array rule. See #82. Thanks to @RebeccaStevens for adding this option! (See PR #95)

v4.8.0 - 2018-10-07

Added

  • New option ignore-rest-parameters for the readonly-array rule. See #73. Thanks to @aboyton for adding this option! (See PR #93)

Added

v4.7.0 - 2018-08-23

Added

  • New option ignore-mutation-following-accessor for the no-array-mutation rule. See #88. Thanks to @RebeccaStevens for adding this option! (See PR #89)

  • New rules no-throw and no-try. See #86. Thanks to @RebeccaStevens for adding these rules! (See PR #91)

  • Option for enabling all the rules with tslint-immutable/all. See #66. Thanks to @bakerface for adding this! (See PR #85)

v4.6.0 - 2018-06-12

Added

v4.5.4 - 2018-04-17

  • no-object-mutation rule, allow class member mutation in constructor #79.

  • readonly-keyword rule, check function params and return type #80

v4.5.3 - 2018-03-31

Fixed

  • readonly-array fixer does not work for arrays with nested template type. See #24. Thanks to @geon for fixing this longstanding bug! (See PR #78)

v4.5.2 - 2018-02-27

Fixed

  • Ignore await when checking ignore-prefix in no-expression-statement. See #76.

  • no-class does not catch class expressions. See #65. Thanks to @ianbollinger for this fix! (See PR #70)

v4.5.1 - 2018-01-16

Fixed

  • no-mixed-interface does not understand arrow function notation. See #62. Thanks to @geon for this fix! (See PR #63)

v4.5.0 - 2017-12-29

Added

  • New options ignore-interface, and ignore-class for the readonly-keyword rule. See #44 for background. Thanks to @aboyton for these options! (See PR #57)

  • The ignore-prefix option can be an array for all rules (previously just for no-expression-statement and no-object-mutation).

  • New rule no-delete. See readme for more info.

  • New rule no-if-statement. See readme for more info and #54 for discussion.

  • New rule no-loop-statement. See readme for more info and #54 for discussion.

Fixed

  • no-mixed-interface does not understand arrow function notation. See #60.

v4.4.0 - 2017-09-27

Added

  • New option ignore-prefix for the no-object-mutation rule. See #43 for background. Thanks to @miangraham for this option! (See PR #53)

v4.3.0 - 2017-09-23

Fixed

  • The readonly-keyword rule now properly checks for readonly modifier of class property declarations. See #49 and PR #50.

Added

v4.2.1 - 2017-09-21

Fixed

  • The readonly-array rule with ignore-local option does not work within class. See 45.

v4.2.0 - 2017-09-14

Added

  • New option ignore-prefix for the no-expression-statement rule. See #39 for background. Thanks to @algesten for this option! (See PR #42)

v4.1.0 - 2017-08-21

Added

  • New rule no-object-mutation. See #36 for background. Thanks to @miangraham for this rule! (See PR #37)

v4.0.2 - 2017-07-16

Added

  • Added an index.js file to the rules directory in order for rulesDirectory to work. See #35.

v4.0.1 - 2017-06-06

Fixed

  • Invalid default tslint config (it included the removed rules).

v4.0.0 - 2017-06-06

Removed

  • readonly-interface rule. This rule is replaced by the readonly-keyword rule.
  • readonly-indexer rule. This rule is replaced by the readonly-keyword rule.
  • no-new rule. Please see background in #2.
  • no-arguments rule. This rule has been moved to the tslint-divid package.
  • no-label rule. This rule has been moved to the tslint-divid package.
  • no-semicolon-interface rule. This rule has been moved to the tslint-divid package.
  • import-containment rule. This rule has been moved to the tslint-divid package.

v3.4.2 - 2017-05-14

Added

  • Notice in readme about deprecrating the no-new rule.

Deprecated

  • The no-new rule. See #2 for background.

v3.4.1 - 2017-05-14

Added

  • Note in readme about moving the "other" rules. The no-argument, no-label, no-semicolon-interface, and import containtment rules are moving to tslint-divid. See #19 for more information.

Deprecated

  • The no-argument, no-label, no-semicolon-interface, and import containtment rules as noted above.

v3.4.0 - 2017-05-14

Added

  • New rule readonly-keyword, to replace readonly-interface and readonly-indexer #31

Deprecated

  • The readonly-interface, and readonly-indexer rules are deprecated and will be removed in the next major release. Please use the readonly-keyword rule instead.

v3.3.2 - 2017-05-13

Fixed

  • Functions in interfaces cannot have readonly specified but are still checked #28

v3.3.1 - 2017-05-09

Fixed

  • patch: fix main file in package.json. Thanks to @yonbeastie. (see #29)

v3.3.0 - 2017-05-09

Fixed

  • ignore-local does not work for function assigned to const #23

Added

v3.2.0 - 2017-04-10

Fixed

  • readonly-array does not check shorthand syntax in return types with ignore-local option #21

Added

  • Fixer for the readonly-array rule.

v3.1.2 - 2017-04-09

Fixed

  • readonly-array does not check return type when ignore-local is enabled #16
  • readonly-array does not check shorthand syntax #20.

Changed

  • Impicit return type is not checked in readonly-array #18.

v3.1.1 - 2017-04-05

Fixed

  • Function parameters are not checked when using ignore-local option, #13.
  • Implicit Array type by default value for function parameter is not checked, #14.

v3.1.0 - 2017-04-05

Added

v3.0.0 - 2017-04-02

Changed

  • Upgraded to tslint 5.0.0

Added

  • readonly-array now also checks for implicity declared mutable arrays.

v2.1.1 - 2017-03-29

Fixed

  • Remove vestigial noMutationRule.js and no-mutation example from README, thanks to @pmlamotte. (see #6)

v2.1.0 - 2016-12-12

Added

  • readonly-indexer rule.

Fixed

  • Fixed a bug in readonly-interface rule that made it fail on indexer declarations.

v2.0.0 - 2016-12-12

Added

  • readonly-interface rule.
  • readonly-indexer rule.
  • readonly-array rule.
  • no-class rule.
  • no-new rule.
  • no-mixed-interface rule.
  • import-containment rule.
  • no-arguments rule.
  • no-label rule.
  • no-semicolon-interface rule.

Removed

  • no-mutation rule (replaced by the readonly-interface rule).

v1.0.0 - 2016-12-10

Added

  • no-expression-statement rule.
  • no-let rule.
  • no-mutation rule.
  • no-this rule.