Security News
The Push to Ban Ransom Payments Is Gaining Momentum
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
eslint-plugin-ts-immutable
Advanced tools
Readme
ESLint rules to disable mutation in TypeScript.
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.
Make sure you have TypeScript and @typescript-eslint/parser installed, then install the plugin:
npm i eslint-plugin-ts-immutable --save-dev
Note: If you installed ESLint globally (using the -g
flag) then you must also install eslint-plugin-ts-immutable
globally.
Add @typescript-eslint/parser
to the parser
field and ts-immutable
to the plugins section of your .eslintrc
configuration file. Then configure the rules you want to use under the rules section.
{
"parser": "@typescript-eslint/parser",
"plugins": ["ts-immutable"],
"rules": {
"@typescript-eslint/rule-name": "error"
}
}
You can also enable all the recommended rules for our plugin:
{
"extends": ["plugin:ts-immutable/recommended"]
}
If you want to use rules which require type information, you will need to specify a path to your tsconfig.json file in the "project" property of "parserOptions".
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["ts-immutable"],
"rules": {
"ts-immutable/no-array-mutation": "error"
}
}
See @typescript-eslint/parser's README.md for more information on the available "parserOptions".
Note: Make sure to use eslint --ext .js,.ts
since by default eslint
will only search for .js files.
In addition to immutable rules this project also contains a few rules for enforcing a functional style of programming. The following rules are available:
Key: :heavy_check_mark: = recommended, :wrench: = fixable, :thought_balloon: = requires type information
Name | Description | :heavy_check_mark: | :wrench: | :thought_balloon: |
---|---|---|---|---|
ts-immutable/readonly-keyword | Enforce readonly modifiers are used where possible. | :heavy_check_mark: | :wrench: | |
ts-immutable/readonly-array | Prefer readonly array over mutable arrays. | :heavy_check_mark: | :wrench: | |
ts-immutable/no-let | Disallow mutable variables. | :heavy_check_mark: | :wrench: | |
ts-immutable/no-array-mutation | Disallow mutating arrays. | :heavy_check_mark: | :thought_balloon: | |
ts-immutable/no-object-mutation | WIP | :heavy_check_mark: | :thought_balloon: | |
ts-immutable/no-method-signature | Prefer property signatures with readonly modifiers over method signatures. | :heavy_check_mark: | ||
ts-immutable/no-delete | Disallow delete expressions. | :heavy_check_mark: |
Name | Description | :heavy_check_mark: | :wrench: | :thought_balloon: |
---|---|---|---|---|
ts-immutable/no-this | Disallow this access. | :heavy_check_mark: | ||
ts-immutable/no-class | Disallow classes. | :heavy_check_mark: | ||
ts-immutable/no-mixed-interface | Restrict interfaces so that only members of the same kind of are allowed in them. | :heavy_check_mark: | ||
ts-immutable/no-expression-statement | Using expressions to cause side-effects not allowed. | :heavy_check_mark: | ||
ts-immutable/no-if-statement | Disallow if statements. | :heavy_check_mark: | ||
ts-immutable/no-loop-statement | Disallow imperative loops. | :heavy_check_mark: | ||
ts-immutable/no-throw | Disallow throwing exceptions. | :heavy_check_mark: | ||
ts-immutable/no-try | Disallow try-catch[-finally] and try-finally patterns. | :heavy_check_mark: | ||
ts-immutable/no-reject | Disallow try-catch[-finally] and try-finally patterns. | :heavy_check_mark: |
In addition to the immutability rules above, there are a few standard rules that needs to be enabled to achieve immutability.
Without this rule, it is still possible to create var
variables that are mutable.
Without this rule, function parameters are mutable.
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:
function foo() {
return [1, 2, 3];
}
To avoid this situation you can enable @typescript-eslint/explicit-function-return-type
. Now the above function is forced to declare the return type and the mutability will be detected.
For new features file an issue. For bugs, file an issue and optionally file a PR with a failing test.
To execute the tests run yarn test
.
To learn about eslint plugin development se the relevant section of the eslit docs. You can also checkout the typescript-eslint repo which has some more information specific to typescript.
In order to know which AST nodes are created for a snippet of typescript code you can use ast explorer with options JavaScript and @typescript-eslint/parser.
yarn version --patch
yarn version --minor
yarn version --major
This work was originally inspired by eslint-plugin-immutable.
FAQs
ESLint rules to disable mutation in TypeScript.
We found that eslint-plugin-ts-immutable demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
Application Security
New SEC disclosure rules aim to enforce timely cyber incident reporting, but fear of job loss and inadequate resources lead to significant underreporting.
Security News
The Python Software Foundation has secured a 5-year sponsorship from Fastly that supports PSF's activities and events, most notably the security and reliability of the Python Package Index (PyPI).