6.5.1 • Published 9 days ago

eslint-plugin-functional v6.5.1

Weekly downloads
31,104
License
MIT
Repository
github
Last release
9 days ago

eslint-logo

eslint-plugin-functional

npm version CI Coverage Status semantic-release code style: prettier MIT license GitHub Discussions

An ESLint plugin to disable mutation and promote functional programming in JavaScript and TypeScript.

:wave: If you previously used the rules in tslint-immutable, this package is the ESLint version of those rules. Please see the migration guide for how to migrate.

Features

No mutations

One 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. Additionally, this project will also aim to support disabling mutability for vanilla JavaScript where possible.

No object-orientation

JavaScript is multi-paradigm, allowing both object-oriented and functional programming styles. In order to promote a functional style, the object oriented features of JavaScript need to be disabled.

No statements

In functional programming everything is an expression that produces a value. JavaScript has a lot of syntax that is just statements that does not produce a value. That syntax has to be disabled to promote a functional style.

No exceptions

Functional programming style does not use run-time exceptions. Instead expressions produces values to indicate errors.

Currying

JavaScript functions support syntax that is not compatible with curried functions. To enable currying this syntax has to be disabled.

Stylistic

Make things look nicer (in our opinion).

Installation

JavaScript

# Install with npm
npm install eslint eslint-plugin-functional --save-dev

# Install with yarn
yarn add -D eslint eslint-plugin-functional

Note: If you installed ESLint globally (using the -g flag with npm or global with yarn) then you must also install eslint-plugin-functional globally.

TypeScript

To use this plugin with TypeScript, a TypeScript parser for ESLint is needed. We recommend @typescript-eslint/parser.

# Install with npm
npm install eslint @typescript-eslint/parser eslint-plugin-functional --save-dev

# Install with yarn
yarn add -D eslint @typescript-eslint/parser eslint-plugin-functional

tsutils is also recommended as a peer dependency but if you are using @typescript-eslint/eslint-plugin then you don't need explicitly add it.

Usage

Add functional to the plugins section of your .eslintrc configuration file. Then configure the rules you want to use under the rules section.

{
  "plugins": ["functional"],
  "rules": {
    "functional/rule-name": "error"
  }
}

There are several rulesets provided by this plugin. See below for what they are and what rules are including in each. Enable rulesets via the "extends" property of your .eslintrc configuration file.

{
  // ...
  "extends": [
    "plugin:functional/external-recommended",
    "plugin:functional/recommended",
    "plugin:functional/stylistic"
  ]
}

With TypeScript

Add @typescript-eslint/parser to the "parser" filed in your .eslintrc configuration file. To use 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"
  }
}

See @typescript-eslint/parser's README.md for more information on the available parser options.

Example Config

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "tsconfig.json"
  },
  "env": {
    "es6": true
  },
  "plugins": [
    "@typescript-eslint",
    "functional"
  ],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
    "plugin:functional/external-recommended",
    "plugin:functional/recommended",
    "plugin:functional/stylistic"
  ]
}

Rulesets

The following rulesets are made available by this plugin:

Presets:

  • Recommended (plugin:functional/recommended)
  • Lite (plugin:functional/lite)

Categorized:

  • No Mutations (plugin:functional/no-mutations)
  • No Object Orientation (plugin:functional/no-object-orientation)
  • No Statements (plugin:functional/no-statements)
  • No Exceptions (plugin:functional/no-exceptions)
  • Currying (plugin:functional/currying)
  • Stylistic (plugin:functional/stylistic)

Other:

  • All (plugin:functional/all) - Enables all rules defined in this plugin.
  • External Recommended (plugin:functional/external-recommended) - Configures recommended rules not defined by this plugin.

The below section gives details on which rules are enabled by each ruleset.

Supported Rules

Key:

SymbolMeaning
:hear_no_evil:Ruleset: LiteThis ruleset is designed to enforce a somewhat functional programming code style.
:speak_no_evil:Ruleset: RecommendedThis ruleset is designed to enforce a functional programming code style.
:wrench:FixableProblems found by this rule are potentially fixable with the --fix option.
:thought_balloon:Only Available for TypeScriptThe rule either requires Type Information or only works with TypeScript syntax.
:blue_heart:Works better with TypeScriptType Information will be used if available making the rule work in more cases.

No Mutations Rules

:see_no_evil: = no-mutations Ruleset.

NameDescription:see_no_evil::hear_no_evil::speak_no_evil::wrench::blue_heart:
immutable-dataDisallow mutating objects and arrays:heavy_check_mark::heavy_check_mark::heavy_check_mark::blue_heart:
no-letDisallow mutable variables:heavy_check_mark::heavy_check_mark::heavy_check_mark:
no-method-signatureEnforce property signatures with readonly modifiers over method signatures:heavy_check_mark::heavy_check_mark::heavy_check_mark::thought_balloon:
prefer-readonly-typeUse readonly types and readonly modifiers where possible:heavy_check_mark::heavy_check_mark::heavy_check_mark::wrench::thought_balloon:

No Object-Orientation Rules

:see_no_evil: = no-object-orientation Ruleset.

NameDescription:see_no_evil::hear_no_evil::speak_no_evil::wrench::blue_heart:
no-classDisallow classes:heavy_check_mark::heavy_check_mark::heavy_check_mark:
no-mixed-typeRestrict types so that only members of the same kind are allowed in them:heavy_check_mark::heavy_check_mark::heavy_check_mark::thought_balloon:
no-this-expressionDisallow this access:heavy_check_mark::heavy_check_mark::heavy_check_mark:

No Statements Rules

:see_no_evil: = no-statements Ruleset.

NameDescription:see_no_evil::hear_no_evil::speak_no_evil::wrench::blue_heart:
no-conditional-statementDisallow conditional statements (if and switch statements):heavy_check_mark::heavy_check_mark::thought_balloon:
no-expression-statementDisallow expressions to cause side-effects:heavy_check_mark::heavy_check_mark::thought_balloon:
no-loop-statementDisallow imperative loops:heavy_check_mark::heavy_check_mark::heavy_check_mark:
no-return-voidDisallow functions that return nothing:heavy_check_mark::heavy_check_mark::heavy_check_mark::thought_balloon:

No Exceptions Rules

:see_no_evil: = no-exceptions Ruleset.

NameDescription:see_no_evil::hear_no_evil::speak_no_evil::wrench::blue_heart:
no-promise-rejectDisallow rejecting Promises
no-throw-statementDisallow throwing exceptions:heavy_check_mark::heavy_check_mark::heavy_check_mark:
no-try-statementDisallow try-catch-finally and try-finally patterns:heavy_check_mark::heavy_check_mark:

Currying Rules

:see_no_evil: = currying Ruleset.

NameDescription:see_no_evil::hear_no_evil::speak_no_evil::wrench::blue_heart:
functional-parametersFunctions must have functional parameters:heavy_check_mark::heavy_check_mark::heavy_check_mark:

Stylistic Rules

:see_no_evil: = stylistic Ruleset.

NameDescription:see_no_evil::hear_no_evil::speak_no_evil::wrench::blue_heart:
prefer-tacitTacit/Point-Free style.:heavy_check_mark::heavy_check_mark::heavy_check_mark::wrench::thought_balloon:

Recommended standard rules

In addition to the immutability rules above, there are a few standard rules that need to be enabled to achieve immutability.

These rules are all included in the external-recommended rulesets.

no-var

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

no-param-reassign

Without this rule, function parameters are mutable.

prefer-const

This rule is helpful when converting from an imperative code style to a functional one.

@typescript-eslint/prefer-readonly

This rule is helpful when working with classes.

@typescript-eslint/prefer-readonly-parameter-types

Functional functions must not modify any data passed into them. This rule marks mutable parameters as a violation as they prevent readonly versions of that data from being passed in.

However, due to many 3rd-party libraries only providing mutable versions of their types, often it can not be easy to satisfy this rule. Thus by default we only enable this rule with the "warn" severity rather than "error".

@typescript-eslint/switch-exhaustiveness-check

Although our no-conditional-statement rule also performs this check, this rule has a fixer that will implement the unimplemented cases which can be useful.

How to contribute

For new features file an issue. For bugs, file an issue and optionally file a PR with a failing test.

How to develop

To execute the tests run yarn test.

To learn about ESLint plugin development see the relevant section of the ESLint 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.

Commit Messages

tl;dr: use npx cz instead of git commit.

Commit messages must follow Conventional Commit messages guidelines. You can use npx cz instead of git commit to run a interactive prompt to generate the commit message. We've customize the prompt specifically for this project. For more information see commitizen.

How to publish

Publishing is handled by semantic release - there shouldn't be any need to publish manually.

Prior work

This project started off as a port of tslint-immutable which was originally inspired by eslint-plugin-immutable.

@ridedott/eslint-config@infrascript/config-eslint@configscript/config-eslinteslint-config-gojutineslint-config-aps@infinitebrahmanuniverse/nolb-eslint-plugin-f@everything-registry/sub-chunk-1611@functorfactory/eslint-config@grantheaslip/eslint-config@hendacorp/eslint-plugin@grapp/eslint-config@ghslp/eslint-configeslint-config-strict-mode@juln/fabriceslint-plugin-mmkal@koober/eslint-config@linters/eslint-config-functional@lou.codes/configs@mozisan/eslint-config@mozisan/eslint-plugin@mblabs/eslint-config@maxxxxxdlp/eslint-config@megabytelabs/eslint-config@m4thieulavoie/linting@mntm/eslint-config@natlibfi/eslint-config-melinda-backend@natlibfi/eslint-config-melinda-frontendeslint-config-chimeraanteslint-config-centraeslint-config-current-thingeslint-config-code-smellseslint-config-ethang-test@lbenie/linting@ishtar-gate/eslint-config-customeslint-config-sammyeslint-config-safe-securityeslint-config-shinyeslint-config-timetree@edgelogistics/eslint-plugin-frontend-reactjs-typescripteslint-config-hardcoreeslint-config-heimdalleslint-config-jag-nodejseslint-config-masmotteslint-config-meriteslint-config-aabccd021@projectdiscoveryio/eslint-config@rainstormy/preset-eslint-base@rainstormy/presets-eslint@pagopa/eslint-config@shoveller/eslint-config@shoveller/eslint-config-react@shoveller/eslint-config-vue@enormora/eslint-config-typescript@touchspot/eslint-plugin@trapcodien/eslint-config@tachibana-shin/eslint-config@foray1010/eslint-config@brummelte/eslint-confignazna@api3/commons@typeofweb/eslint-plugin@washingtondc/eslint@atomic-tools/eslint-config-atomic@apsphysics/eslint-config@chubbyts/chubbyts-eslint@code-quality/eslint-config-functional@brokerse/configs@techsky/eslint-config@wise/eslint-config@whitebird/eslint-config@vangware/configslinter-bundle@tinkoff/linters@ahiho/eslint-config@chocolab/configs@developpeurdurable/nx-workspace-pluginweb-ui-deps
7.0.0-alpha.1

9 days ago

7.0.0-alpha.0

12 days ago

6.5.1

12 days ago

6.5.0

12 days ago

6.4.1

13 days ago

6.3.2

26 days ago

6.3.1

26 days ago

6.4.0

26 days ago

6.3.0

1 month ago

6.2.3

1 month ago

6.2.2

1 month ago

6.2.1

1 month ago

6.2.0

1 month ago

6.2.0-next.3

1 month ago

6.2.0-next.2

1 month ago

6.2.0-next.1

1 month ago

6.1.0

2 months ago

6.1.1

2 months ago

6.0.1

2 months ago

6.0.0

9 months ago

6.0.0-next.1

10 months ago

6.0.0-next.2

10 months ago

6.0.0-next.3

9 months ago

6.0.0-next.4

9 months ago

6.0.0-next.5

9 months ago

6.0.0-next.6

9 months ago

6.0.0-next.7

9 months ago

5.0.8

1 year ago

5.0.7

1 year ago

5.0.6

1 year ago

5.0.5

1 year ago

5.0.0-beta.16

1 year ago

5.0.4

1 year ago

5.0.3

1 year ago

5.0.2

1 year ago

5.0.1

1 year ago

5.0.0

1 year ago

5.0.0-beta.8

2 years ago

5.0.0-beta.9

2 years ago

5.0.0-beta.11

2 years ago

5.0.0-beta.12

1 year ago

5.0.0-beta.10

2 years ago

5.0.0-beta.15

1 year ago

5.0.0-beta.13

1 year ago

5.0.0-beta.14

1 year ago

4.4.0-beta.1

2 years ago

5.0.0-beta.6

2 years ago

5.0.0-beta.7

2 years ago

5.0.0-beta.4

2 years ago

5.0.0-beta.5

2 years ago

5.0.0-beta.2

2 years ago

5.0.0-beta.3

2 years ago

5.0.0-beta.1

2 years ago

4.4.1

2 years ago

4.4.0

2 years ago

4.3.2

2 years ago

4.3.1

2 years ago

4.3.1-beta.1

2 years ago

4.3.0

2 years ago

4.2.2

2 years ago

4.2.1

2 years ago

4.1.1-beta.1

2 years ago

4.1.0

2 years ago

4.2.0

2 years ago

4.1.1

2 years ago

4.0.1

3 years ago

4.0.2

3 years ago

4.0.0-rc2

3 years ago

4.0.0

3 years ago

4.0.0-rc1

3 years ago

3.7.2

3 years ago

3.7.1

3 years ago

3.7.0

3 years ago

3.6.0

3 years ago

3.5.0

3 years ago

3.4.0

3 years ago

3.4.1

3 years ago

3.3.0

3 years ago

3.2.2

3 years ago

3.2.1

3 years ago

3.2.0

3 years ago

3.1.0

4 years ago

3.0.2

4 years ago

3.0.1

4 years ago

3.0.0

4 years ago

1.0.3

4 years ago

2.0.0

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

5 years ago

1.0.0-rc.2

5 years ago

1.0.0-rc.1

5 years ago

0.5.3

5 years ago

0.5.2

5 years ago

0.5.1

5 years ago

0.5.0

5 years ago

0.4.0

5 years ago