Socket
Socket
Sign inDemoInstall

eslint-plugin-functional

Package Overview
Dependencies
215
Maintainers
1
Versions
105
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    eslint-plugin-functional

ESLint rules to disable mutation and promote fp in TypeScript.


Version published
Maintainers
1
Created

Changelog

Source

v1.0.1 - 2019-12-11

Merged

Fixed

  • fix(typeguards): only assume types if type information is not avaliable #72

Readme

Source

eslint-plugin-functional

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

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

Introduction

: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.

This package has a collection of eslint rules to promote functional programming style concepts. Note that you can use this package to enforce only some aspects of functional programming, for example only immutability. There are also options for the rules that allow you to gradually adopt a functional style. Most rules can be used both for JavaScript and TypeScript, however some rules, for example enforcing the readonly keyword, is of course only available for TypeScript.

We've identified the following areas that need to be linted in order to promote functional style in TypeScript/JavaScript:

No mutations

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 have 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. (Although you lose 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. TypeScript 3.0 has continued to add support immutability enforcing syntax. This enables us to use regular objects and arrays and have the immutability enforced 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 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.

Installing

npm install eslint eslint-plugin-functional --save-dev

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

To use this plugin with TypeScript, additionally install @typescript-eslint/parser.

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

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.

You can enable one of these rulesets like so:

{
  "extends": ["plugin:functional/recommended"]
}

With TypeScript

@typescript-eslint/parser is needed to parse TypeScript code; add @typescript-eslint/parser to the "parser" filed in your .eslintrc configuration file. Additionally, for this plugin 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"
  },
  "plugins": ["functional"],
  "rules": {
    "functional/rule-name": "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.

Supported Rules

Key:

SymbolMeaning
:hear_no_evil:Ruleset: Lite
This ruleset is designed to enforce a somewhat functional programming code style.
:speak_no_evil:Ruleset: Recommended
This ruleset is designed to enforce a functional programming code style.
:wrench:Fixable
Problems found by this rule are potentially fixable with the --fix option.
:thought_balloon:Only Avaliable for TypeScript
The rule either requires Type Information or only works with TypeScript syntax.
:blue_heart:Works better with TypeScript
Type 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:
prefer-type-literalUse type literals over interfaces:heavy_check_mark::heavy_check_mark::heavy_check_mark::thought_balloon:

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:
no-expression-statementDisallow expressions to cause side-effects:heavy_check_mark::heavy_check_mark:
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:

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

Each of these rules are enabled by default in the rulesets this plugin provides.

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/explicit-function-return-type

For performance reasons, eslint-plugin-functional does not check implicit return types. So for example this function will return a 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.

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.

How to publish

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

Prior work

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

Keywords

FAQs

Last updated on 11 Dec 2019

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.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc