Socket
Socket
Sign inDemoInstall

eslint-plugin-ts-immutable

Package Overview
Dependencies
162
Maintainers
2
Versions
4
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.1 to 0.3.0

58

CHANGELOG.md

@@ -1,28 +0,54 @@

# Change Log
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [Unreleased](https://github.com/jonaskello/eslint-plugin-ts-immutable/compare/v0.3.0...HEAD)
## [v0.2.1] - 2019-07-12
## [v0.3.0](https://github.com/jonaskello/eslint-plugin-ts-immutable/compare/v0.2.1...v0.3.0)
Remove fixer for `no-let`.
TypeScript is no longer imported unless it is available.
### Merged
## [v0.2.0] - 2019-07-12
- ReadonlySet and ReadonlyMap [`#30`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/30)
- prefer-readonly-types [`#29`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/29)
- no-return-void [`#28`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/28)
- functional-parameters [`#27`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/27)
- feat(readonly-keyword) Add support for parameter properties [`#26`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/26)
- no-conditional-statement [`#23`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/23)
- chore: Remove no-delete rule. [`#21`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/21)
- new rule: immutable-data [`#22`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/22)
This is the first release where things should work. All the rules have been ported over from "ts-immutable" and tests are in place.
Four configs are available: `recommended`, `functional-lite`, `functional` and `all`.
### Fixed
## [v0.1.0] - 2019-07-01
- feat(immutable-data): Prevent object mutation methods. [`#16`](https://github.com/jonaskello/eslint-plugin-ts-immutable/issues/16)
### Added
## [v0.2.1](https://github.com/jonaskello/eslint-plugin-ts-immutable/compare/v0.2.0...v0.2.1) - 2019-07-12
### Merged
- Remove no-let fixer [`#14`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/14)
### Fixed
- TypeScript is no longer imported unless it is available.
## [v0.2.0](https://github.com/jonaskello/eslint-plugin-ts-immutable/compare/v0.1.0...v0.2.0) - 2019-07-12
### Merged
- docs: Update supported rules. [`#8`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/8)
- Make the code more functional [`#9`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/9)
- Added ignoreAccessorPattern, ignorePattern now uses Regex matching [`#7`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/7)
- Ignore option fix [`#6`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/6)
- Consistent file casing [`#5`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/5)
- Port docs for each rule [`#3`](https://github.com/jonaskello/eslint-plugin-ts-immutable/pull/3)
### Fixed
- feat(ignore-option): Add ignoreAccessorPattern option to deal with accessors and switch ignorePatter [`#4`](https://github.com/jonaskello/eslint-plugin-ts-immutable/issues/4)
## [v0.1.0](https://github.com/jonaskello/eslint-plugin-ts-immutable/releases/tag/v0.1.0) - 2019-07-01
This is the first release and everything is experimental at this point.
[unreleased]: https://github.com/jonaskello/eslint-plugin-ts-immutable/compare/v0.2.0...master
[v0.2.0]: https://github.com/jonaskello/eslint-plugin-ts-immutable/releases/tag/v0.2.0
[v0.1.0]: https://github.com/jonaskello/eslint-plugin-ts-immutable/releases/tag/v0.1.0

@@ -8,15 +8,15 @@ 'use strict';

var escapeRegExp = _interopDefault(require('escape-string-regexp'));
var typescriptEstree = require('@typescript-eslint/typescript-estree');
var experimentalUtils = require('@typescript-eslint/experimental-utils');
var astNodeTypes = require('@typescript-eslint/typescript-estree/dist/ts-estree/ast-node-types');
var tslib_1 = require('tslib');
var config = {
rules: {
"ts-immutable/no-array-mutation": "error",
"ts-immutable/immutable-data": "error",
"ts-immutable/no-class": "error",
"ts-immutable/no-delete": "error",
"ts-immutable/no-conditional-statement": "error",
"ts-immutable/no-expression-statement": "error",
"ts-immutable/no-if-statement": "error",
"ts-immutable/no-let": "error",
"ts-immutable/no-loop-statement": "error",
"ts-immutable/no-object-mutation": "error",
"ts-immutable/no-reject": "error",

@@ -33,4 +33,3 @@ "ts-immutable/no-this": "error",

"ts-immutable/no-mixed-interface": "error",
"ts-immutable/readonly-array": "error",
"ts-immutable/readonly-keyword": "error"
"ts-immutable/prefer-readonly-types": "error"
}

@@ -51,3 +50,10 @@ }

rules: {
"@typescript-eslint/explicit-function-return-type": "warn"
"@typescript-eslint/explicit-function-return-type": [
"error",
{
allowExpressions: true,
allowTypedFunctionExpressions: true,
allowHigherOrderFunctions: true
}
]
}

@@ -63,4 +69,3 @@ }

"ts-immutable/no-let": "error",
"ts-immutable/no-object-mutation": "error",
"ts-immutable/no-delete": "error"
"ts-immutable/immutable-data": "error"
},

@@ -71,6 +76,4 @@ overrides: [

rules: {
"ts-immutable/no-array-mutation": "error",
"ts-immutable/no-method-signature": "warn",
"ts-immutable/readonly-array": "error",
"ts-immutable/readonly-keyword": "error"
"ts-immutable/prefer-readonly-types": "error"
}

@@ -89,3 +92,9 @@ }

"ts-immutable/no-loop-statement": "error",
"ts-immutable/no-throw": "error"
"ts-immutable/no-conditional-statement": [
"error",
{ allowReturningBranches: true }
],
"ts-immutable/no-throw": "error",
"ts-immutable/no-return-void": "error",
"ts-immutable/functional-parameters": "error"
},

@@ -107,4 +116,4 @@ overrides: [

rules: {
"ts-immutable/no-conditional-statement": "error",
"ts-immutable/no-expression-statement": "error",
"ts-immutable/no-if-statement": "error",
"ts-immutable/no-try": "error"

@@ -115,4 +124,14 @@ }

// Conditionally loaded TypeScript but only if it is avaliable.
var ts = (function () {
try {
return require("typescript");
}
catch (error) {
return undefined;
}
})();
/**
* This file has functions that typeguard the given node/type.
* @file Functions that typeguard the given node/type.
*/

@@ -122,57 +141,98 @@ /*

*/
function isArrayExpression(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.ArrayExpression;
}
function isAssignmentExpression(node) {
return node.type === "AssignmentExpression";
return node.type === typescriptEstree.AST_NODE_TYPES.AssignmentExpression;
}
function isAssignmentPattern(node) {
return node.type === "AssignmentPattern";
return node.type === typescriptEstree.AST_NODE_TYPES.AssignmentPattern;
}
function isArrayExpression(node) {
return node.type === "ArrayExpression";
function isBlockStatement(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.BlockStatement;
}
function isCallExpression(node) {
return node.type === "CallExpression";
return node.type === typescriptEstree.AST_NODE_TYPES.CallExpression;
}
/**
* Is the given node a class node?
*
* It doesn't matter what type of class.
*/
function isClassLike(node) {
return node.type === "ClassDeclaration" || node.type === "ClassExpression";
return (node.type === typescriptEstree.AST_NODE_TYPES.ClassDeclaration ||
node.type === typescriptEstree.AST_NODE_TYPES.ClassExpression);
}
/**
* Is the given node a function node?
*
* It doesn't matter what type of function.
*/
function isFunctionLike(node) {
return (node.type === "FunctionDeclaration" ||
node.type === "FunctionExpression" ||
node.type === "ArrowFunctionExpression");
return (node.type === typescriptEstree.AST_NODE_TYPES.FunctionDeclaration ||
node.type === typescriptEstree.AST_NODE_TYPES.FunctionExpression ||
node.type === typescriptEstree.AST_NODE_TYPES.ArrowFunctionExpression);
}
function isIdentifier(node) {
return node.type === "Identifier";
return node.type === typescriptEstree.AST_NODE_TYPES.Identifier;
}
function isIfStatement(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.IfStatement;
}
function isMemberExpression(node) {
return node.type === "MemberExpression";
return node.type === typescriptEstree.AST_NODE_TYPES.MemberExpression;
}
function isMethodDefinition(node) {
return node.type === "MethodDefinition";
return node.type === typescriptEstree.AST_NODE_TYPES.MethodDefinition;
}
function isNewExpression(node) {
return node.type === "NewExpression";
return node.type === typescriptEstree.AST_NODE_TYPES.NewExpression;
}
function isProperty(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.Property;
}
function isRestElement(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.RestElement;
}
function isReturnStatement(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.ReturnStatement;
}
function isTSArrayType(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.TSArrayType;
}
function isTSIndexSignature(node) {
return node.type === "TSIndexSignature";
return node.type === typescriptEstree.AST_NODE_TYPES.TSIndexSignature;
}
function isTSInterfaceBody(node) {
return node.type === "TSInterfaceBody";
return node.type === typescriptEstree.AST_NODE_TYPES.TSInterfaceBody;
}
function isTSArrayType(node) {
return node.type === "TSArrayType";
function isTSNullKeyword(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.TSNullKeyword;
}
function isTSParameterProperty(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.TSParameterProperty;
}
function isTSPropertySignature(node) {
return node.type === "TSPropertySignature";
return node.type === typescriptEstree.AST_NODE_TYPES.TSPropertySignature;
}
function isTSTupleType(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.TSTupleType;
}
function isTSTypeAliasDeclaration(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.TSTypeAliasDeclaration;
}
function isTSTypeOperator(node) {
return node.type === "TSTypeOperator";
return node.type === typescriptEstree.AST_NODE_TYPES.TSTypeOperator;
}
function isTypeAliasDeclaration(node) {
return node.type === "TSTypeAliasDeclaration";
function isTSUndefinedKeyword(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.TSUndefinedKeyword;
}
function isTSVoidKeyword(node) {
return node.type === typescriptEstree.AST_NODE_TYPES.TSVoidKeyword;
}
function isVariableDeclaration(node) {
return node.type === "VariableDeclaration";
return node.type === typescriptEstree.AST_NODE_TYPES.VariableDeclaration;
}
function isVariableDeclarator(node) {
return node.type === "VariableDeclarator";
return node.type === typescriptEstree.AST_NODE_TYPES.VariableDeclarator;
}

@@ -183,27 +243,46 @@ /*

function isUnionType(type) {
// TODO: Find a nicer why to conditionally require typescript.
/* eslint-disable-next-line ts-immutable/no-try */
try {
// Cannot use top-level typescript import - that is for types only, not values.
/* eslint-disable-next-line @typescript-eslint/no-require-imports */
return type.flags === require("typescript").TypeFlags.Union;
}
catch (error) {
return false;
}
return ts !== undefined && type.flags === ts.TypeFlags.Union;
}
function isArrayType(type) {
return ((type.symbol && type.symbol.name === "Array") ||
(isUnionType(type) && type.types.some(isArrayType)));
function isArrayType(type, assumeType, node) {
if (assumeType === void 0) { assumeType = false; }
if (node === void 0) { node = null; }
return assumeType === true
? node !== null
: type !== null &&
((type.symbol && type.symbol.name === "Array") ||
(isUnionType(type) &&
type.types.some(function (t) { return isArrayType(t, false, null); })));
}
function isArrayConstructorType(type) {
return ((type.symbol && type.symbol.name === "ArrayConstructor") ||
(isUnionType(type) && type.types.some(isArrayConstructorType)));
function isArrayConstructorType(type, assumeType, node) {
if (assumeType === void 0) { assumeType = false; }
if (node === void 0) { node = null; }
return assumeType === true
? node !== null && isIdentifier(node) && node.name === "Array"
: type !== null &&
((type.symbol && type.symbol.name === "ArrayConstructor") ||
(isUnionType(type) &&
type.types.some(function (t) { return isArrayConstructorType(t, false, null); })));
}
function isObjectConstructorType(type) {
return ((type.symbol && type.symbol.name === "ObjectConstructor") ||
(isUnionType(type) && type.types.some(isObjectConstructorType)));
function isObjectConstructorType(type, assumeType, node) {
if (assumeType === void 0) { assumeType = false; }
if (node === void 0) { node = null; }
return assumeType === true
? node !== null && isIdentifier(node) && node.name === "Object"
: type !== null &&
((type.symbol && type.symbol.name === "ObjectConstructor") ||
(isUnionType(type) &&
type.types.some(function (t) { return isObjectConstructorType(t, false, null); })));
}
/**
* Return the parent that meets the given check criteria.
*/
function getParentOfType(checker, node) {
return checker(node)
? node
: node.parent == undefined
? null
: getParentOfType(checker, node.parent);
}
/**
* Test if the given node is in a function.

@@ -246,11 +325,17 @@ */

/**
* Return the parent that meets the given check criteria.
* Is the given identifier a property of an object?
*/
function getParentOfType(checker, node) {
return checker(node)
? node
: node.parent == undefined
? null
: getParentOfType(checker, node.parent);
function isPropertyAccess(node) {
return (node.parent !== undefined &&
isMemberExpression(node.parent) &&
node.parent.property === node);
}
/**
* Is the given identifier a property name?
*/
function isPropertyName(node) {
return (node.parent !== undefined &&
isProperty(node.parent) &&
node.parent.key === node);
}

@@ -318,42 +403,17 @@ // Polyfill.

};
var ignoreNewArrayOptionSchema = {
type: "object",
properties: {
ignoreNewArray: {
type: "boolean"
}
},
additionalProperties: false
};
/**
* Should the given node be ignored?
* Recursive callback of `getNodeText`.
*
* This function not be called from anywhere else.
*/
function shouldIgnore(node, context, ignoreOptions) {
return (
// Ignore if in a function and ignoreLocal is set.
(Boolean(ignoreOptions.ignoreLocal) && inFunction(node)) ||
// Ignore if in a class and ignoreClass is set.
(Boolean(ignoreOptions.ignoreClass) && inClass(node)) ||
// Ignore if in an interface and ignoreInterface is set.
(Boolean(ignoreOptions.ignoreInterface) && inInterface(node)) ||
(function (texts) {
return texts.length > 0
? // Ignore if ignorePattern is set and a pattern matches.
(ignoreOptions.ignorePattern !== undefined &&
texts.every(function (text) {
return isIgnoredPattern(text, ignoreOptions.ignorePattern);
})) ||
// Ignore if ignoreAccessorPattern is set and an accessor pattern matches.
(ignoreOptions.ignoreAccessorPattern !== undefined &&
texts.every(function (text) {
return isIgnoredAccessorPattern(text, ignoreOptions.ignoreAccessorPattern);
}))
: false;
})(getNodeTexts(node, context)));
function _getNodeText(node, context) {
return isIdentifier(node)
? node.name
: isMemberExpression(node)
? _getNodeText(node.object, context) + "." + _getNodeText(node.property, context)
: context.getSourceCode().getText(node);
}
function getNodeTexts(node, context) {
return (isVariableDeclaration(node)
? node.declarations.flatMap(function (declarator) { return getNodeText(declarator, context); })
: [getNodeText(node, context)]).filter(function (name) { return name !== undefined; });
}
/**
* Get the text of the given node.
*/
function getNodeText(node, context) {

@@ -366,3 +426,3 @@ return isAssignmentExpression(node)

? _getNodeText(node.object, context)
: isVariableDeclarator(node) || isTypeAliasDeclaration(node)
: isVariableDeclarator(node) || isTSTypeAliasDeclaration(node)
? _getNodeText(node.id, context)

@@ -373,10 +433,16 @@ : isTSPropertySignature(node)

}
function _getNodeText(node, context) {
return isIdentifier(node)
? node.name
: isMemberExpression(node)
? _getNodeText(node.object, context) + "." + _getNodeText(node.property, context)
: context.getSourceCode().getText(node);
/**
* Get all the important bits of texts from the given node.
*/
function getNodeTexts(node, context) {
return (isVariableDeclaration(node)
? node.declarations.flatMap(function (declarator) { return getNodeText(declarator, context); })
: [getNodeText(node, context)]).filter(function (name) { return name !== undefined; });
}
function isIgnoredPattern(text, ignorePattern) {
/**
* Should the given text be ignore?
*
* Test using the given pattern(s).
*/
function shouldIgnoreViaPattern(text, ignorePattern) {
var patterns = Array.isArray(ignorePattern)

@@ -388,12 +454,10 @@ ? ignorePattern

}
function isIgnoredAccessorPattern(text, ignorePattern) {
var patterns = Array.isArray(ignorePattern)
? ignorePattern
: [ignorePattern];
// One or more patterns match?
return patterns.some(function (pattern) {
return findMatch(pattern.split("."), text.split("."));
});
}
function findMatch(_a, textParts, allowExtra) {
/**
* Recursive callback of `shouldIgnoreViaAccessorPattern`.
*
* This function not be called from anywhere else.
*
* Does the given text match the given pattern.
*/
function accessorPatternMatch(_a, textParts, allowExtra) {
var pattern = _a[0], remainingPatternParts = _a.slice(1);

@@ -406,7 +470,7 @@ if (allowExtra === void 0) { allowExtra = false; }

? textParts.length === 0
? findMatch(remainingPatternParts, [], allowExtra)
? accessorPatternMatch(remainingPatternParts, [], allowExtra)
: Array.from({ length: textParts.length })
.map(function (_element, index) { return index; })
.some(function (offset) {
return findMatch(remainingPatternParts, textParts.slice(offset), true);
return accessorPatternMatch(remainingPatternParts, textParts.slice(offset), true);
})

@@ -416,8 +480,49 @@ : // Match anything?

? textParts.length > 0 &&
findMatch(remainingPatternParts, textParts.slice(1), allowExtra)
accessorPatternMatch(remainingPatternParts, textParts.slice(1), allowExtra)
: // Text matches pattern?
new RegExp("^" + escapeRegExp(pattern).replace(/\\\*/g, ".*") + "$").test(textParts[0]) && findMatch(remainingPatternParts, textParts.slice(1), allowExtra);
new RegExp("^" + escapeRegExp(pattern).replace(/\\\*/g, ".*") + "$").test(textParts[0]) &&
accessorPatternMatch(remainingPatternParts, textParts.slice(1), allowExtra);
}
/**
* Should the given text be ignore?
*
* Test using the given accessor pattern(s).
*/
function shouldIgnoreViaAccessorPattern(text, ignorePattern) {
var patterns = Array.isArray(ignorePattern)
? ignorePattern
: [ignorePattern];
// One or more patterns match?
return patterns.some(function (pattern) {
return accessorPatternMatch(pattern.split("."), text.split("."));
});
}
/**
* Should the given node be ignored?
*/
function shouldIgnore(node, context, options) {
return (
// Ignore if in a function and ignoreLocal is set.
(Boolean(options.ignoreLocal) && inFunction(node)) ||
// Ignore if in a class and ignoreClass is set.
(Boolean(options.ignoreClass) && inClass(node)) ||
// Ignore if in an interface and ignoreInterface is set.
(Boolean(options.ignoreInterface) && inInterface(node)) ||
(function (texts) {
return texts.length > 0
? // Ignore if ignorePattern is set and a pattern matches.
(options.ignorePattern !== undefined &&
texts.every(function (text) {
return shouldIgnoreViaPattern(text, options.ignorePattern);
})) ||
// Ignore if ignoreAccessorPattern is set and an accessor pattern matches.
(options.ignoreAccessorPattern !== undefined &&
texts.every(function (text) {
return shouldIgnoreViaAccessorPattern(text, options.ignoreAccessorPattern);
}))
: false;
})(getNodeTexts(node, context)));
}
const version = "0.2.0";
const version = "0.2.1";

@@ -427,7 +532,19 @@ /**

*/
function createRule(data) {
function createRule(name, meta, defaultOptions, create) {
return experimentalUtils.ESLintUtils.RuleCreator(function (name) {
return "https://github.com/jonaskello/eslint-plugin-ts-immutable/blob/v" + version + "/docs/rules/" + name + ".md";
})(data);
})({
name: name,
meta: meta,
defaultOptions: [defaultOptions],
create: function (c, _a) {
var o = _a[0];
return create(c, o);
}
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
});
}
// This function can't be functional as it needs to interact with 3rd-party
// libraries that aren't functional.
/* eslint-disable ts-immutable/no-return-void, ts-immutable/no-conditional-statement, ts-immutable/no-expression-statement */
/**

@@ -437,10 +554,6 @@ * Create a function that processes common options and then runs the given

*/
function checkNode(check, context, ignoreOptions, otherOptions) {
if (otherOptions === void 0) { otherOptions = []; }
function checkNode(check, context, options) {
return function (node) {
// This function can't be functional as it needs to interact with 3rd-party
// libraries that aren't functional.
/* eslint-disable ts-immutable/no-if-statement, ts-immutable/no-expression-statement */
if (!ignoreOptions || !shouldIgnore(node, context, ignoreOptions)) {
var result_1 = check(node, context, [ignoreOptions].concat(otherOptions).filter(function (option) { return option !== undefined; }));
if (!options || !shouldIgnore(node, context, options)) {
var result_1 = check(node, context, options);
result_1.descriptors.forEach(function (descriptor) {

@@ -450,5 +563,5 @@ return result_1.context.report(descriptor);

}
/* eslint-enable ts-immutable/no-if-statement, ts-immutable/no-expression-statement */
};
}
/* eslint-enable ts-immutable/no-return-void, ts-immutable/no-conditional-statement, ts-immutable/no-expression-statement */
/**

@@ -458,68 +571,212 @@ * Get the type of the the given node.

function getTypeOfNode(node, context) {
var parserServices = getParserServices(context);
return parserServices.program
.getTypeChecker()
.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
var parserServices = context.parserServices;
return parserServices === undefined ||
parserServices.program === undefined ||
parserServices.esTreeNodeToTSNodeMap === undefined
? null
: parserServices.program
.getTypeChecker()
.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node));
}
// The name of this rule.
var name = "functional-parameters";
// The schema for the rule options.
var schema = [
deepmerge.all([
ignorePatternOptionSchema,
{
type: "object",
properties: {
allowRestParameter: {
type: "boolean"
},
allowArgumentsKeyword: {
type: "boolean"
},
enforceParameterCount: {
oneOf: [
{
type: "boolean",
enum: [false]
},
{
type: "string",
enum: ["atLeastOne", "exactlyOne"]
}
]
}
},
additionalProperties: false
}
])
];
// The default options for the rule.
var defaultOptions = {
allowRestParameter: false,
allowArgumentsKeyword: false,
enforceParameterCount: "atLeastOne"
};
// The possible error messages.
var errorMessages = {
restParam: "Unexpected rest parameter. Use a regular parameter of type array instead.",
arguments: "Unexpected use of `arguments`. Use regular function arguments instead.",
paramCountAtLeastOne: "Functions must have at least one parameter.",
paramCountExactlyOne: "Functions must have exactly one parameter."
};
// The meta data for this rule.
var meta = {
type: "suggestion",
docs: {
description: "Enforce functional parameters.",
category: "Best Practices",
recommended: false
},
messages: errorMessages,
schema: schema
};
/**
* Ensure the type info is avaliable.
* Get the rest parameter violations.
*/
function parserServicesAvaliable(context) {
return (context.parserServices !== undefined &&
context.parserServices.program !== undefined &&
context.parserServices.esTreeNodeToTSNodeMap !== undefined);
function getRestParamViolations(allowRestParameter, node) {
return !allowRestParameter &&
node.params.length > 0 &&
isRestElement(node.params[node.params.length - 1])
? [
{
node: node.params[node.params.length - 1],
messageId: "restParam"
}
]
: [];
}
/**
* Ensure the type info is avaliable.
* Get the parameter count violations.
*/
function getParserServices(context) {
/* eslint-disable-next-line ts-immutable/no-if-statement */
if (parserServicesAvaliable(context)) {
return context.parserServices;
}
/**
* The user needs to have configured "project" in their parserOptions
* for @typescript-eslint/parser
*/
/* eslint-disable-next-line ts-immutable/no-throw */
throw new Error('You have used a rule which is only avaliable for TypeScript files and requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.');
function getParamCountViolations(enforceParameterCount, node) {
return enforceParameterCount === "atLeastOne" && node.params.length < 1
? [
{
node: node,
messageId: "paramCountAtLeastOne"
}
]
: enforceParameterCount === "exactlyOne" && node.params.length !== 1
? [
{
node: node,
messageId: "paramCountExactlyOne"
}
]
: [];
}
/**
* Check if the given function node has a reset parameter this rule.
*/
function checkFunction(node, context, options) {
return {
context: context,
descriptors: getRestParamViolations(options.allowRestParameter, node).concat(getParamCountViolations(options.enforceParameterCount, node))
};
}
/**
* Check if the given identifier is for the "arguments" keyword.
*/
function checkIdentifier(node, context, options) {
return {
context: context,
descriptors: !options.allowArgumentsKeyword &&
node.name === "arguments" &&
!isPropertyName(node) &&
!isPropertyAccess(node)
? [
{
node: node,
messageId: "arguments"
}
]
: []
};
}
// Create the rule.
var rule = createRule(name, meta, defaultOptions, function (context, options) {
var _checkFunction = checkNode(checkFunction, context, options);
var _checkIdentifier = checkNode(checkIdentifier, context, options);
return {
FunctionDeclaration: _checkFunction,
FunctionExpression: _checkFunction,
ArrowFunctionExpression: _checkFunction,
Identifier: _checkIdentifier
};
});
/**
* Returns a function that checks if the given value is the same as the expected
* value.
*/
function isExpected(expected) {
return function (actual) { return actual === expected; };
}
// The name of this rule.
var name = "no-array-mutation";
var name$1 = "immutable-data";
// The schema for the rule options.
var schema = [
var schema$1 = [
deepmerge.all([
ignorePatternOptionSchema,
ignoreAccessorPatternOptionSchema,
ignoreNewArrayOptionSchema
{
type: "object",
properties: {
assumeTypes: {
oneOf: [
{
type: "boolean"
},
{
type: "object",
properties: {
forArrays: {
type: "boolean"
},
forObjects: {
type: "boolean"
}
},
additionalProperties: false
}
]
}
},
additionalProperties: false
}
])
];
// The default options for the rule.
var defaultOptions = [
{
ignoreNewArray: true
}
];
var defaultOptions$1 = {
assumeTypes: true
};
// The possible error messages.
var errorMessages = {
generic: "Mutating an array is not allowed."
var errorMessages$1 = {
generic: "Modifying an existing object/array is not allowed.",
object: "Modifying properties of existing object not allowed.",
array: "Modifying an array is not allowed."
};
// The meta data for this rule.
var meta = {
var meta$1 = {
type: "suggestion",
docs: {
description: "Disallow mutating arrays.",
description: "Enforce treating data as immutable.",
category: "Best Practices",
recommended: "error"
},
messages: errorMessages,
schema: schema
messages: errorMessages$1,
schema: schema$1
};
/**
* Methods that mutate an array.
* Array methods that mutate an array.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Methods#Mutator_methods
*/
var mutatorMethods = [
var arrayMutatorMethods = [
"copyWithin",

@@ -536,3 +793,3 @@ "fill",

/**
* Methods that return a new array without mutating the original.
* Array methods that return a new object (or array) without mutating the original.
*

@@ -542,3 +799,3 @@ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Methods#Accessor_methods

*/
var newArrayReturningMethods = [
var arrayNewObjectReturningMethods = [
"concat",

@@ -552,10 +809,21 @@ "slice",

/**
* Functions that create a new array.
* Array constructor functions that create a new array.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Methods
*/
var constructorFunctions = ["from", "of"];
var arrayConstructorFunctions = ["from", "of"];
/**
* Check if the given node violates this rule.
* Object constructor functions that mutate an object.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Methods_of_the_Object_constructor
*/
var objectConstructorMutatorFunctions = [
"assign",
"defineProperties",
"defineProperty",
"setPrototypeOf"
];
/**
* Check if the given assignment expression violates this rule.
*/
function checkAssignmentExpression(node, context) {

@@ -565,3 +833,4 @@ return {

descriptors: isMemberExpression(node.left) &&
isArrayType(getTypeOfNode(node.left.object, context))
// Ignore if in a constructor - allow for field initialization.
!inConstructor(node)
? [{ node: node, messageId: "generic" }]

@@ -577,5 +846,3 @@ : []

context: context,
descriptors: node.operator === "delete" &&
isMemberExpression(node.argument) &&
isArrayType(getTypeOfNode(node.argument.object, context))
descriptors: node.operator === "delete" && isMemberExpression(node.argument)
? [{ node: node, messageId: "generic" }]

@@ -591,4 +858,3 @@ : []

context: context,
descriptors: isMemberExpression(node.argument) &&
isArrayType(getTypeOfNode(node.argument.object, context))
descriptors: isMemberExpression(node.argument)
? [{ node: node, messageId: "generic" }]

@@ -599,29 +865,2 @@ : []

/**
* Check if the given node violates this rule.
*/
function checkCallExpression(node, context, _a) {
var options = _a[0];
return {
context: context,
descriptors: isMemberExpression(node.callee) &&
isIdentifier(node.callee.property) &&
mutatorMethods.some(function (m) {
return m ===
node.callee
.property.name;
}) &&
(!options.ignoreNewArray ||
!isInChainCallAndFollowsNew(node.callee, context)) &&
isArrayType(getTypeOfNode(node.callee.object, context))
? [{ node: node, messageId: "generic" }]
: []
};
}
/**
* Returns a function that checks if the given value is the same as the expected value.
*/
function isExpected(expected) {
return function (actual) { return actual === expected; };
}
/**
* Check if the given the given MemberExpression is part of a chain and

@@ -633,3 +872,3 @@ * immediately follows a method/function call that returns a new array.

*/
function isInChainCallAndFollowsNew(node, context) {
function isInChainCallAndFollowsNew(node, context, assumeArrayTypes) {
return (

@@ -640,42 +879,77 @@ // Check for: [0, 1, 2]

((isNewExpression(node.object) &&
isArrayConstructorType(getTypeOfNode(node.object.callee, context))) ||
isArrayConstructorType(getTypeOfNode(node.object.callee, context), assumeArrayTypes, node.object.callee)) ||
(isCallExpression(node.object) &&
isMemberExpression(node.object.callee) &&
isIdentifier(node.object.callee.property) &&
// Check for: Object.from(iterable)
((constructorFunctions.some(isExpected(node.object.callee.property.name)) &&
isArrayConstructorType(getTypeOfNode(node.object.callee.object, context))) ||
// Check for: Array.from(iterable)
((arrayConstructorFunctions.some(isExpected(node.object.callee.property.name)) &&
isArrayConstructorType(getTypeOfNode(node.object.callee.object, context), assumeArrayTypes, node.object.callee.object)) ||
// Check for: array.slice(0)
newArrayReturningMethods.some(isExpected(node.object.callee.property.name))))));
arrayNewObjectReturningMethods.some(isExpected(node.object.callee.property.name))))));
}
/**
* Check if the given node violates this rule.
*/
function checkCallExpression(node, context, options) {
var assumeTypesForArrays = options.assumeTypes === true ||
(options.assumeTypes !== false && Boolean(options.assumeTypes.forArrays));
var assumeTypesForObjects = options.assumeTypes === true ||
(options.assumeTypes !== false && Boolean(options.assumeTypes.forObjects));
return {
context: context,
descriptors:
// Potential object mutation?
isMemberExpression(node.callee) && isIdentifier(node.callee.property)
? // Potential array mutation?
arrayMutatorMethods.some(function (m) {
return m ===
node.callee
.property.name;
}) &&
!isInChainCallAndFollowsNew(node.callee, context, assumeTypesForArrays) &&
isArrayType(getTypeOfNode(node.callee.object, context), assumeTypesForArrays, node.callee.object)
? [{ node: node, messageId: "array" }]
: // Potential non-array object mutation (ex. Object.assign on identifier)?
objectConstructorMutatorFunctions.some(function (m) {
return m ===
node.callee
.property.name;
}) &&
node.arguments.length >= 2 &&
(isIdentifier(node.arguments[0]) ||
isMemberExpression(node.arguments[0])) &&
isObjectConstructorType(getTypeOfNode(node.callee.object, context), assumeTypesForObjects, node.callee.object)
? [{ node: node, messageId: "object" }]
: []
: []
};
}
// Create the rule.
var rule = createRule({
name: name,
meta: meta,
defaultOptions: defaultOptions,
create: function (context, _a) {
var ignoreOptions = _a[0], otherOptions = _a.slice(1);
var _checkAssignmentExpression = checkNode(checkAssignmentExpression, context, ignoreOptions, otherOptions);
var _checkUnaryExpression = checkNode(checkUnaryExpression, context, ignoreOptions, otherOptions);
var _checkUpdateExpression = checkNode(checkUpdateExpression, context, ignoreOptions, otherOptions);
var _checkCallExpression = checkNode(checkCallExpression, context, ignoreOptions, otherOptions);
return {
AssignmentExpression: _checkAssignmentExpression,
UnaryExpression: _checkUnaryExpression,
UpdateExpression: _checkUpdateExpression,
CallExpression: _checkCallExpression
};
}
var rule$1 = createRule(name$1, meta$1, defaultOptions$1, function (context, options) {
var _checkAssignmentExpression = checkNode(checkAssignmentExpression, context, options);
var _checkUnaryExpression = checkNode(checkUnaryExpression, context, options);
var _checkUpdateExpression = checkNode(checkUpdateExpression, context, options);
// This functionality is only avaliable if the parser services are
// avaliable.
var _checkCallExpression = checkNode(checkCallExpression, context, options);
return {
AssignmentExpression: _checkAssignmentExpression,
UnaryExpression: _checkUnaryExpression,
UpdateExpression: _checkUpdateExpression,
CallExpression: _checkCallExpression
};
});
// The name of this rule.
var name$1 = "no-class";
var name$2 = "no-class";
// The schema for the rule options.
var schema$2 = [];
// The default options for the rule.
var defaultOptions$1 = [];
var defaultOptions$2 = {};
// The possible error messages.
var errorMessages$1 = {
var errorMessages$2 = {
generic: "Unexpected class, use functions not classes."
};
// The meta data for this rule.
var meta$1 = {
var meta$2 = {
type: "suggestion",

@@ -687,4 +961,4 @@ docs: {

},
messages: errorMessages$1,
schema: []
messages: errorMessages$2,
schema: schema$2
};

@@ -699,155 +973,260 @@ /**

// Create the rule.
var rule$1 = createRule({
name: name$1,
meta: meta$1,
defaultOptions: defaultOptions$1,
create: function (context) {
var _checkClass = checkNode(checkClass, context);
return {
ClassDeclaration: _checkClass,
ClassExpression: _checkClass
};
}
var rule$2 = createRule(name$2, meta$2, defaultOptions$2, function (context, options) {
var _checkClass = checkNode(checkClass, context, options);
return {
ClassDeclaration: _checkClass,
ClassExpression: _checkClass
};
});
// The name of this rule.
var name$2 = "no-delete";
var name$3 = "no-return-void";
// The schema for the rule options.
var schema$3 = [
{
type: "object",
properties: {
allowNull: {
type: "boolean"
},
allowUndefined: {
type: "boolean"
}
},
additionalProperties: false
}
];
// The default options for the rule.
var defaultOptions$2 = [];
var defaultOptions$3 = {
allowNull: true,
allowUndefined: true
};
// The possible error messages.
var errorMessages$2 = {
generic: "Unexpected delete, objects should be considered immutable."
var errorMessages$3 = {
generic: "Function must return a value."
};
// The meta data for this rule.
var meta$2 = {
var meta$3 = {
type: "suggestion",
docs: {
description: "Disallow delete expressions.",
description: "Disallow functions that don't return anything.",
category: "Best Practices",
recommended: "error"
recommended: false
},
messages: errorMessages$2,
schema: []
messages: errorMessages$3,
schema: schema$3
};
/**
* Check if the given UnaryExpression violates this rule.
* Check if the given function node violates this rule.
*/
function checkUnaryExpression$1(node, context) {
function checkFunction$1(node, context, options) {
return {
context: context,
descriptors: node.operator === "delete" ? [{ node: node, messageId: "generic" }] : []
descriptors: node.returnType !== undefined &&
(isTSVoidKeyword(node.returnType.typeAnnotation) ||
(!options.allowNull &&
isTSNullKeyword(node.returnType.typeAnnotation)) ||
(!options.allowUndefined &&
isTSUndefinedKeyword(node.returnType.typeAnnotation)))
? [{ node: node.returnType, messageId: "generic" }]
: []
};
}
// Create the rule.
var rule$2 = createRule({
name: name$2,
meta: meta$2,
defaultOptions: defaultOptions$2,
create: function (context) {
var _checkUnaryExpression = checkNode(checkUnaryExpression$1, context);
return {
UnaryExpression: _checkUnaryExpression
};
}
var rule$3 = createRule(name$3, meta$3, defaultOptions$3, function (context, options) {
var _checkFunction = checkNode(checkFunction$1, context, options);
return {
FunctionDeclaration: _checkFunction,
FunctionExpression: _checkFunction,
ArrowFunctionExpression: _checkFunction,
TSFunctionType: _checkFunction
};
});
// The name of this rule.
var name$3 = "no-expression-statement";
var name$4 = "no-conditional-statement";
// The schema for the rule options.
var schema$1 = [ignorePatternOptionSchema];
var schema$4 = [
{
type: "object",
properties: {
allowReturningBranches: {
oneOf: [
{
type: "boolean"
},
{
type: "string",
enum: ["ifExhaustive"]
}
]
}
},
additionalProperties: false
}
];
// The default options for the rule.
var defaultOptions$3 = [{}];
var defaultOptions$4 = { allowReturningBranches: false };
// The possible error messages.
var errorMessages$3 = {
generic: "Using expressions to cause side-effects not allowed."
var errorMessages$4 = {
incompleteBranch: "Incomplete branch, every branch in a conditional statement must contain a return statement.",
incompleteIf: "Incomplete if, it must have an else statement and every branch must contain a return statement.",
incompleteSwitch: "Incomplete switch, it must have an default case and every case must contain a return statement.",
unexpectedIf: "Unexpected if, use a conditional expression (ternary operator) instead.",
unexpectedSwitch: "Unexpected switch, use a conditional expression (ternary operator) instead."
};
// The meta data for this rule.
var meta$3 = {
var meta$4 = {
type: "suggestion",
docs: {
description: "Disallow expression statements.",
description: "Disallow conditional statements.",
category: "Best Practices",
recommended: false
},
messages: errorMessages$3,
schema: schema$1
messages: errorMessages$4,
schema: schema$4
};
/**
* Check if the given ExpressionStatement violates this rule.
* Get all of the violations in the given if statement assuming if statements
* are allowed.
*/
function checkExpressionStatement(node, context) {
// All expression statements violate this rule.
return { context: context, descriptors: [{ node: node, messageId: "generic" }] };
function getIfBranchViolations(node) {
var nodes = [node.consequent, node.alternate].reduce(function (carry, branch) {
return branch === null ||
isReturnStatement(branch) ||
(isBlockStatement(branch) &&
branch.body.some(function (statement) {
return isReturnStatement(statement) ||
// Another instance of this rule will check nested if statements.
isIfStatement(statement);
})) ||
isIfStatement(branch)
? carry
: carry.concat([branch]);
}, []);
return nodes.flatMap(function (node) { return [{ node: node, messageId: "incompleteBranch" }]; });
}
/**
* Get all of the violations in the given switch statement assuming switch
* statements are allowed.
*/
function getSwitchViolations(node) {
var nodes = node.cases.reduce(function (carry, branch) {
return branch.consequent.length === 0 ||
branch.consequent.some(isReturnStatement) ||
(branch.consequent.every(isBlockStatement) &&
branch.consequent[branch.consequent.length - 1].body.some(isReturnStatement))
? carry
: carry.concat([branch]);
}, []);
return nodes.flatMap(function (node) { return [{ node: node, messageId: "incompleteBranch" }]; });
}
/**
* Does the given if statement violate this rule if it must be exhaustive.
*/
function isExhaustiveIfViolation(node) {
return node.alternate === null;
}
/**
* Does the given switch statement violate this rule if it must be exhaustive.
*/
function isExhaustiveSwitchViolation(node) {
return (
// No cases defined.
node.cases.length === 0 ||
// No default case defined.
node.cases.every(function (c) { return c.test !== null; }));
}
/**
* Check if the given IfStatement violates this rule.
*/
function checkIfStatement(node, context, options) {
return {
context: context,
descriptors: options.allowReturningBranches
? options.allowReturningBranches === "ifExhaustive"
? isExhaustiveIfViolation(node)
? [{ node: node, messageId: "incompleteIf" }]
: getIfBranchViolations(node)
: getIfBranchViolations(node)
: [{ node: node, messageId: "unexpectedIf" }]
};
}
/**
* Check if the given SwitchStatement violates this rule.
*/
function checkSwitchStatement(node, context, options) {
return {
context: context,
descriptors: options.allowReturningBranches
? options.allowReturningBranches === "ifExhaustive"
? isExhaustiveSwitchViolation(node)
? [{ node: node, messageId: "incompleteSwitch" }]
: getSwitchViolations(node)
: getSwitchViolations(node)
: [{ node: node, messageId: "unexpectedSwitch" }]
};
}
// Create the rule.
var rule$3 = createRule({
name: name$3,
meta: meta$3,
defaultOptions: defaultOptions$3,
create: function (context, _a) {
var ignoreOptions = _a[0], otherOptions = _a.slice(1);
var _checkExpressionStatement = checkNode(checkExpressionStatement, context, ignoreOptions, otherOptions);
return {
ExpressionStatement: _checkExpressionStatement
};
}
var rule$4 = createRule(name$4, meta$4, defaultOptions$4, function (context, options) {
var _checkIfStatement = checkNode(checkIfStatement, context, options);
var _checkSwitchStatement = checkNode(checkSwitchStatement, context, options);
return {
IfStatement: _checkIfStatement,
SwitchStatement: _checkSwitchStatement
};
});
// The name of this rule.
var name$4 = "no-if-statement";
var name$5 = "no-expression-statement";
// The schema for the rule options.
var schema$5 = [ignorePatternOptionSchema];
// The default options for the rule.
var defaultOptions$4 = [];
var defaultOptions$5 = {};
// The possible error messages.
var errorMessages$4 = {
generic: "Unexpected if, use a conditional expression (ternary operator) instead."
var errorMessages$5 = {
generic: "Using expressions to cause side-effects not allowed."
};
// The meta data for this rule.
var meta$4 = {
var meta$5 = {
type: "suggestion",
docs: {
description: "Disallow if statements.",
description: "Disallow expression statements.",
category: "Best Practices",
recommended: false
},
messages: errorMessages$4,
schema: []
messages: errorMessages$5,
schema: schema$5
};
/**
* Check if the given IfStatement violates this rule.
* Check if the given ExpressionStatement violates this rule.
*/
function checkIfStatement(node, context) {
// All if statements violate this rule.
function checkExpressionStatement(node, context) {
// All expression statements violate this rule.
return { context: context, descriptors: [{ node: node, messageId: "generic" }] };
}
// Create the rule.
var rule$4 = createRule({
name: name$4,
meta: meta$4,
defaultOptions: defaultOptions$4,
create: function (context) {
var _checkIfStatement = checkNode(checkIfStatement, context);
return {
IfStatement: _checkIfStatement
};
}
var rule$5 = createRule(name$5, meta$5, defaultOptions$5, function (context, options) {
var _checkExpressionStatement = checkNode(checkExpressionStatement, context, options);
return {
ExpressionStatement: _checkExpressionStatement
};
});
// The name of this rule.
var name$5 = "no-let";
var name$6 = "no-let";
// The schema for the rule options.
var schema$2 = [
var schema$6 = [
deepmerge.all([ignoreLocalOptionSchema, ignorePatternOptionSchema])
];
// The default options for the rule.
var defaultOptions$5 = [
{
ignoreLocal: false
}
];
var defaultOptions$6 = {
ignoreLocal: false
};
// The possible error messages.
var errorMessages$5 = {
var errorMessages$6 = {
generic: "Unexpected let, use const instead."
};
// The meta data for this rule.
var meta$5 = {
var meta$6 = {
type: "suggestion",

@@ -859,5 +1238,5 @@ docs: {

},
messages: errorMessages$5,
messages: errorMessages$6,
fixable: "code",
schema: schema$2
schema: schema$6
};

@@ -874,25 +1253,21 @@ /**

// Create the rule.
var rule$5 = createRule({
name: name$5,
meta: meta$5,
defaultOptions: defaultOptions$5,
create: function (context, _a) {
var ignoreOptions = _a[0], otherOptions = _a.slice(1);
var _checkVariableDeclaration = checkNode(checkVariableDeclaration, context, ignoreOptions, otherOptions);
return {
VariableDeclaration: _checkVariableDeclaration
};
}
var rule$6 = createRule(name$6, meta$6, defaultOptions$6, function (context, options) {
var _checkVariableDeclaration = checkNode(checkVariableDeclaration, context, options);
return {
VariableDeclaration: _checkVariableDeclaration
};
});
// The name of this rule.
var name$6 = "no-loop-statement";
var name$7 = "no-loop-statement";
// The schema for the rule options.
var schema$7 = [];
// The default options for the rule.
var defaultOptions$6 = [];
var defaultOptions$7 = {};
// The possible error messages.
var errorMessages$6 = {
var errorMessages$7 = {
generic: "Unexpected loop, use map or reduce instead."
};
// The meta data for this rule.
var meta$6 = {
var meta$7 = {
type: "suggestion",

@@ -904,4 +1279,4 @@ docs: {

},
messages: errorMessages$6,
schema: []
messages: errorMessages$7,
schema: schema$7
};

@@ -916,134 +1291,124 @@ /**

// Create the rule.
var rule$6 = createRule({
name: name$6,
meta: meta$6,
defaultOptions: defaultOptions$6,
create: function (context) {
var _checkLoop = checkNode(checkLoop, context);
return {
ForStatement: _checkLoop,
ForInStatement: _checkLoop,
ForOfStatement: _checkLoop,
WhileStatement: _checkLoop,
DoWhileStatement: _checkLoop
};
}
var rule$7 = createRule(name$7, meta$7, defaultOptions$7, function (context, options) {
var _checkLoop = checkNode(checkLoop, context, options);
return {
ForStatement: _checkLoop,
ForInStatement: _checkLoop,
ForOfStatement: _checkLoop,
WhileStatement: _checkLoop,
DoWhileStatement: _checkLoop
};
});
// The name of this rule.
var name$7 = "no-object-mutation";
var name$8 = "no-method-signature";
// The schema for the rule options.
var schema$3 = [
deepmerge.all([
ignorePatternOptionSchema,
ignoreAccessorPatternOptionSchema
])
];
var schema$8 = [];
// The default options for the rule.
var defaultOptions$7 = [{}];
var defaultOptions$8 = {};
// The possible error messages.
var errorMessages$7 = {
generic: "Modifying properties of existing object not allowed."
var errorMessages$8 = {
generic: "Method signature is mutable, use property signature with readonly modifier instead."
};
// The meta data for this rule.
var meta$7 = {
var meta$8 = {
type: "suggestion",
docs: {
description: "Disallow mutating objects.",
description: "Prefer property signatures with readonly modifiers over method signatures.",
category: "Best Practices",
recommended: "error"
},
messages: errorMessages$7,
schema: schema$3
messages: errorMessages$8,
schema: schema$8
};
/**
* Check if the given assignment expression violates this rule.
* Check if the given TSMethodSignature violates this rule.
*/
function checkAssignmentExpression$1(node, context) {
return {
context: context,
descriptors: isMemberExpression(node.left) &&
// Ignore if in a constructor - allow for field initialization.
!inConstructor(node)
? [{ node: node, messageId: "generic" }]
: []
};
function checkTSMethodSignature(node, context) {
// All TS method signatures violate this rule.
return { context: context, descriptors: [{ node: node, messageId: "generic" }] };
}
/**
* Check if the given node violates this rule.
*/
function checkUnaryExpression$2(node, context) {
// Create the rule.
var rule$8 = createRule(name$8, meta$8, defaultOptions$8, function (context, options) {
var _checkTSMethodSignature = checkNode(checkTSMethodSignature, context, options);
return {
context: context,
descriptors: node.operator === "delete" && isMemberExpression(node.argument)
? [{ node: node, messageId: "generic" }]
: []
TSMethodSignature: _checkTSMethodSignature
};
}
});
// The name of this rule.
var name$9 = "no-mixed-interface";
// The schema for the rule options.
var schema$9 = [];
// The default options for the rule.
var defaultOptions$9 = {};
// The possible error messages.
var errorMessages$9 = {
generic: "Only the same kind of members allowed in interfaces."
};
// The meta data for this rule.
var meta$9 = {
type: "suggestion",
docs: {
description: "Restrict interfaces so that only members of the same kind of are allowed in them.",
category: "Best Practices",
recommended: false
},
messages: errorMessages$9,
schema: schema$9
};
/**
* Check if the given node violates this rule.
* Check if the given TSInterfaceDeclaration violates this rule.
*/
function checkUpdateExpression$1(node, context) {
function checkTSInterfaceDeclaration(node, context) {
return {
context: context,
descriptors: isMemberExpression(node.argument)
? [{ node: node, messageId: "generic" }]
: []
descriptors: node.body.body.reduce(function (carry, member) {
var memberType = member.type;
var memberTypeAnnotation = isTSPropertySignature(member) && member.typeAnnotation !== undefined
? member.typeAnnotation.typeAnnotation.type
: undefined;
return {
prevMemberType: memberType,
prevMemberTypeAnnotation: memberTypeAnnotation,
violations:
// Not the first property in the interface.
carry.prevMemberType !== undefined &&
// And different property type to previous property.
(carry.prevMemberType !== memberType ||
// Or annotationed with a different type annotation.
(carry.prevMemberTypeAnnotation !== memberTypeAnnotation &&
// Where one of the properties is a annotationed as a function.
(carry.prevMemberTypeAnnotation ===
astNodeTypes.AST_NODE_TYPES.TSFunctionType ||
memberTypeAnnotation === astNodeTypes.AST_NODE_TYPES.TSFunctionType)))
? carry.violations.concat([{ node: member, messageId: "generic" }]) : carry.violations
};
}, {
prevMemberType: undefined,
prevMemberTypeAnnotation: undefined,
violations: []
}).violations
};
}
/**
* Check if the given node violates this rule.
*/
function checkCallExpression$1(node, context) {
// No Object.assign on identifiers.
// Create the rule.
var rule$9 = createRule(name$9, meta$9, defaultOptions$9, function (context, options) {
var _checkTSInterfaceDeclaration = checkNode(checkTSInterfaceDeclaration, context, options);
return {
context: context,
descriptors: isMemberExpression(node.callee) &&
isIdentifier(node.callee.property) &&
node.callee.property.name === "assign" &&
node.arguments.length >= 2 &&
(isIdentifier(node.arguments[0]) ||
isMemberExpression(node.arguments[0])) &&
// Type checking if avaliable?
((parserServicesAvaliable(context) &&
isObjectConstructorType(getTypeOfNode(node.callee.object, context))) ||
// Type checking not avaliable?
(isIdentifier(node.callee.object) &&
node.callee.object.name === "Object"))
? [{ node: node, messageId: "generic" }]
: []
TSInterfaceDeclaration: _checkTSInterfaceDeclaration
};
}
// Create the rule.
var rule$7 = createRule({
name: name$7,
meta: meta$7,
defaultOptions: defaultOptions$7,
create: function (context, _a) {
var ignoreOptions = _a[0], otherOptions = _a.slice(1);
var _checkAssignmentExpression = checkNode(checkAssignmentExpression$1, context, ignoreOptions, otherOptions);
var _checkUnaryExpression = checkNode(checkUnaryExpression$2, context, ignoreOptions, otherOptions);
var _checkUpdateExpression = checkNode(checkUpdateExpression$1, context, ignoreOptions, otherOptions);
// This functionality is only avaliable if the parser services are
// avaliable.
var _checkCallExpression = checkNode(checkCallExpression$1, context, ignoreOptions, otherOptions);
return {
AssignmentExpression: _checkAssignmentExpression,
UnaryExpression: _checkUnaryExpression,
UpdateExpression: _checkUpdateExpression,
CallExpression: _checkCallExpression
};
}
});
// The name of this rule.
var name$8 = "no-reject";
var name$a = "no-reject";
// The schema for the rule options.
var schema$a = [];
// The default options for the rule.
var defaultOptions$8 = [];
var defaultOptions$a = {};
// The possible error messages.
var errorMessages$8 = {
var errorMessages$a = {
generic: "Unexpected reject, return an error instead."
};
// The meta data for this rule.
var meta$8 = {
var meta$a = {
type: "suggestion",

@@ -1055,4 +1420,4 @@ docs: {

},
messages: errorMessages$8,
schema: []
messages: errorMessages$a,
schema: schema$a
};

@@ -1062,3 +1427,3 @@ /**

*/
function checkCallExpression$2(node, context) {
function checkCallExpression$1(node, context) {
return {

@@ -1076,24 +1441,21 @@ context: context,

// Create the rule.
var rule$8 = createRule({
name: name$8,
meta: meta$8,
defaultOptions: defaultOptions$8,
create: function (context) {
var _checkCallExpression = checkNode(checkCallExpression$2, context);
return {
CallExpression: _checkCallExpression
};
}
var rule$a = createRule(name$a, meta$a, defaultOptions$a, function (context, options) {
var _checkCallExpression = checkNode(checkCallExpression$1, context, options);
return {
CallExpression: _checkCallExpression
};
});
// The name of this rule.
var name$9 = "no-this";
var name$b = "no-this";
// The schema for the rule options.
var schema$b = [];
// The default options for the rule.
var defaultOptions$9 = [];
var defaultOptions$b = {};
// The possible error messages.
var errorMessages$9 = {
var errorMessages$b = {
generic: "Unexpected this, use functions not classes."
};
// The meta data for this rule.
var meta$9 = {
var meta$b = {
type: "suggestion",

@@ -1105,4 +1467,4 @@ docs: {

},
messages: errorMessages$9,
schema: []
messages: errorMessages$b,
schema: schema$b
};

@@ -1117,24 +1479,21 @@ /**

// Create the rule.
var rule$9 = createRule({
name: name$9,
meta: meta$9,
defaultOptions: defaultOptions$9,
create: function (context) {
var _checkThisExpression = checkNode(checkThisExpression, context);
return {
ThisExpression: _checkThisExpression
};
}
var rule$b = createRule(name$b, meta$b, defaultOptions$b, function (context, options) {
var _checkThisExpression = checkNode(checkThisExpression, context, options);
return {
ThisExpression: _checkThisExpression
};
});
// The name of this rule.
var name$a = "no-throw";
var name$c = "no-throw";
// The schema for the rule options.
var schema$c = [];
// The default options for the rule.
var defaultOptions$a = [];
var defaultOptions$c = {};
// The possible error messages.
var errorMessages$a = {
var errorMessages$c = {
generic: "Unexpected throw, throwing exceptions is not functional."
};
// The meta data for this rule.
var meta$a = {
var meta$c = {
type: "suggestion",

@@ -1146,4 +1505,4 @@ docs: {

},
messages: errorMessages$a,
schema: []
messages: errorMessages$c,
schema: schema$c
};

@@ -1158,24 +1517,21 @@ /**

// Create the rule.
var rule$a = createRule({
name: name$a,
meta: meta$a,
defaultOptions: defaultOptions$a,
create: function (context) {
var _checkThrowStatement = checkNode(checkThrowStatement, context);
return {
ThrowStatement: _checkThrowStatement
};
}
var rule$c = createRule(name$c, meta$c, defaultOptions$c, function (context, options) {
var _checkThrowStatement = checkNode(checkThrowStatement, context, options);
return {
ThrowStatement: _checkThrowStatement
};
});
// The name of this rule.
var name$b = "no-try";
var name$d = "no-try";
// The schema for the rule options.
var schema$d = [];
// The default options for the rule.
var defaultOptions$b = [];
var defaultOptions$d = {};
// The possible error messages.
var errorMessages$b = {
var errorMessages$d = {
generic: "Unexpected try, the try-catch[-finally] and try-finally patterns are not functional."
};
// The meta data for this rule.
var meta$b = {
var meta$d = {
type: "suggestion",

@@ -1187,4 +1543,4 @@ docs: {

},
messages: errorMessages$b,
schema: []
messages: errorMessages$d,
schema: schema$d
};

@@ -1199,141 +1555,45 @@ /**

// Create the rule.
var rule$b = createRule({
name: name$b,
meta: meta$b,
defaultOptions: defaultOptions$b,
create: function (context) {
var _checkTryStatement = checkNode(checkTryStatement, context);
return {
TryStatement: _checkTryStatement
};
}
});
// The name of this rule.
var name$c = "no-method-signature";
// The default options for the rule.
var defaultOptions$c = [];
// The possible error messages.
var errorMessages$c = {
generic: "Method signature is mutable, use property signature with readonly modifier instead."
};
// The meta data for this rule.
var meta$c = {
type: "suggestion",
docs: {
description: "Prefer property signatures with readonly modifiers over method signatures.",
category: "Best Practices",
recommended: "error"
},
messages: errorMessages$c,
schema: []
};
/**
* Check if the given TSMethodSignature violates this rule.
*/
function checkTSMethodSignature(node, context) {
// All TS method signatures violate this rule.
return { context: context, descriptors: [{ node: node, messageId: "generic" }] };
}
// Create the rule.
var rule$c = createRule({
name: name$c,
meta: meta$c,
defaultOptions: defaultOptions$c,
create: function (context) {
var _checkTSMethodSignature = checkNode(checkTSMethodSignature, context);
return {
TSMethodSignature: _checkTSMethodSignature
};
}
});
// The name of this rule.
var name$d = "no-mixed-interface";
// The default options for the rule.
var defaultOptions$d = [];
// The possible error messages.
var errorMessages$d = {
generic: "Only the same kind of members allowed in interfaces."
};
// The meta data for this rule.
var meta$d = {
type: "suggestion",
docs: {
description: "Restrict interfaces so that only members of the same kind of are allowed in them.",
category: "Best Practices",
recommended: false
},
messages: errorMessages$d,
schema: []
};
/**
* Check if the given TSInterfaceDeclaration violates this rule.
*/
function checkTSInterfaceDeclaration(node, context) {
var rule$d = createRule(name$d, meta$d, defaultOptions$d, function (context, options) {
var _checkTryStatement = checkNode(checkTryStatement, context, options);
return {
context: context,
descriptors: node.body.body.reduce(function (carry, member) {
var memberType = member.type;
var memberTypeAnnotation = isTSPropertySignature(member) && member.typeAnnotation !== undefined
? member.typeAnnotation.typeAnnotation.type
: undefined;
return {
prevMemberType: memberType,
prevMemberTypeAnnotation: memberTypeAnnotation,
violations:
// Not the first property in the interface.
carry.prevMemberType !== undefined &&
// And different property type to previous property.
(carry.prevMemberType !== memberType ||
// Or annotationed with a different type annotation.
(carry.prevMemberTypeAnnotation !== memberTypeAnnotation &&
// Where one of the properties is a annotationed as a function.
(carry.prevMemberTypeAnnotation ===
astNodeTypes.AST_NODE_TYPES.TSFunctionType ||
memberTypeAnnotation === astNodeTypes.AST_NODE_TYPES.TSFunctionType)))
? carry.violations.concat([{ node: member, messageId: "generic" }]) : carry.violations
};
}, {
prevMemberType: undefined,
prevMemberTypeAnnotation: undefined,
violations: []
}).violations
TryStatement: _checkTryStatement
};
}
// Create the rule.
var rule$d = createRule({
name: name$d,
meta: meta$d,
defaultOptions: defaultOptions$d,
create: function (context) {
var _checkTSInterfaceDeclaration = checkNode(checkTSInterfaceDeclaration, context);
return {
TSInterfaceDeclaration: _checkTSInterfaceDeclaration
};
}
});
// Polyfill.
// The name of this rule.
var name$e = "readonly-array";
var name$e = "prefer-readonly-types";
// The schema for the rule options.
var schema$4 = [
var schema$e = [
deepmerge.all([
ignoreLocalOptionSchema,
ignorePatternOptionSchema,
ignoreReturnTypeOptionSchema
ignoreClassOptionSchema,
ignoreInterfaceOptionSchema,
ignoreReturnTypeOptionSchema,
{
type: "object",
properties: {
checkImplicit: {
type: "boolean"
}
},
additionalProperties: false
}
])
];
// The default options for the rule.
var defaultOptions$e = [
{
ignoreLocal: false,
ignoreReturnType: false
}
];
var defaultOptions$e = {
checkImplicit: false,
ignoreClass: false,
ignoreInterface: false,
ignoreLocal: false,
ignoreReturnType: false
};
// The possible error messages.
var errorMessages$e = {
generic: "Only readonly arrays allowed.",
implicit: "Implicitly a mutable array. Only readonly arrays allowed."
array: "Only readonly arrays allowed.",
implicit: "Implicitly a mutable array. Only readonly arrays allowed.",
property: "A readonly modifier is required.",
tuple: "Only readonly tuples allowed.",
type: "Only readonly types allowed."
};

@@ -1350,9 +1610,9 @@ // The meta data for this rule.

fixable: "code",
schema: schema$4
schema: schema$e
};
var mutableToImmutableTypes = new Map([["Array", "ReadonlyArray"], ["Map", "ReadonlyMap"], ["Set", "ReadonlySet"]]);
/**
* Check if the given ArrayType or TupleType violates this rule.
*/
function checkArrayOrTupleType(node, context, _a) {
var options = _a[0];
function checkArrayOrTupleType(node, context, options) {
return {

@@ -1367,3 +1627,3 @@ context: context,

node: node,
messageId: "generic",
messageId: isTSTupleType(node) ? "tuple" : "array",
fix: node.parent && isTSArrayType(node.parent)

@@ -1383,17 +1643,44 @@ ? function (fixer) { return [

*/
function checkTypeReference(node, context, _a) {
var options = _a[0];
function checkTypeReference(node, context, options) {
if (isIdentifier(node.typeName)) {
var immutableType_1 = mutableToImmutableTypes.get(node.typeName.name);
return {
context: context,
descriptors: immutableType_1 && (!options.ignoreReturnType || !isInReturnType(node))
? [
{
node: node,
messageId: "type",
fix: function (fixer) { return fixer.replaceText(node.typeName, immutableType_1); }
}
]
: []
};
}
else {
return {
context: context,
descriptors: []
};
}
}
/**
* Check if the given property/signature node violates this rule.
*/
function checkProperty(node, context) {
return {
context: context,
descriptors: isIdentifier(node.typeName) &&
node.typeName.name === "Array" &&
(!options.ignoreReturnType || !isInReturnType(node))
? [
descriptors: node.readonly
? []
: [
{
node: node,
messageId: "generic",
fix: function (fixer) { return fixer.insertTextBefore(node, "Readonly"); }
messageId: "property",
fix: isTSIndexSignature(node)
? function (fixer) { return fixer.insertTextBefore(node, "readonly "); }
: isTSParameterProperty(node)
? function (fixer) { return fixer.insertTextBefore(node.parameter, "readonly "); }
: function (fixer) { return fixer.insertTextBefore(node.key, "readonly "); }
}
]
: []
};

@@ -1443,15 +1730,9 @@ }

// Create the rule.
var rule$e = createRule({
name: name$e,
meta: meta$e,
defaultOptions: defaultOptions$e,
create: function (context, _a) {
var ignoreOptions = _a[0], otherOptions = _a.slice(1);
var _checkArrayOrTupleType = checkNode(checkArrayOrTupleType, context, ignoreOptions, otherOptions);
var _checkTypeReference = checkNode(checkTypeReference, context, ignoreOptions, otherOptions);
var _checkImplicitType = checkNode(checkImplicitType, context, ignoreOptions, otherOptions);
return {
TSArrayType: _checkArrayOrTupleType,
TSTupleType: _checkArrayOrTupleType,
TSTypeReference: _checkTypeReference,
var rule$e = createRule(name$e, meta$e, defaultOptions$e, function (context, options) {
var _checkArrayOrTupleType = checkNode(checkArrayOrTupleType, context, options);
var _checkTypeReference = checkNode(checkTypeReference, context, options);
var _checkProperty = checkNode(checkProperty, context, options);
var _checkImplicitType = checkNode(checkImplicitType, context, options);
return tslib_1.__assign({ TSArrayType: _checkArrayOrTupleType, TSTupleType: _checkArrayOrTupleType, TSTypeReference: _checkTypeReference, ClassProperty: _checkProperty, TSIndexSignature: _checkProperty, TSParameterProperty: _checkProperty, TSPropertySignature: _checkProperty }, (options.checkImplicit
? {
VariableDeclaration: _checkImplicitType,

@@ -1461,76 +1742,6 @@ FunctionDeclaration: _checkImplicitType,

ArrowFunctionExpression: _checkImplicitType
};
}
}
: {}));
});
// The name of this rule.
var name$f = "readonly-keyword";
// The schema for the rule options.
var schema$5 = [
deepmerge.all([
ignoreLocalOptionSchema,
ignorePatternOptionSchema,
ignoreClassOptionSchema,
ignoreInterfaceOptionSchema
])
];
// The default options for the rule.
var defaultOptions$f = [
{
ignoreClass: false,
ignoreInterface: false,
ignoreLocal: false
}
];
// The possible error messages.
var errorMessages$f = {
generic: "A readonly modifier is required."
};
// The meta data for this rule.
var meta$f = {
type: "suggestion",
docs: {
description: "Enforce readonly modifiers are used where possible.",
category: "Best Practices",
recommended: "error"
},
messages: errorMessages$f,
fixable: "code",
schema: schema$5
};
/**
* Check if the given node violates this rule.
*/
function check(node, context) {
return {
context: context,
descriptors: node.readonly
? []
: [
{
node: node,
messageId: "generic",
fix: isTSIndexSignature(node)
? function (fixer) { return fixer.insertTextBefore(node, "readonly "); }
: function (fixer) { return fixer.insertTextBefore(node.key, "readonly "); }
}
]
};
}
// Create the rule.
var rule$f = createRule({
name: name$f,
meta: meta$f,
defaultOptions: defaultOptions$f,
create: function (context, _a) {
var ignoreOptions = _a[0], otherOptions = _a.slice(1);
var _checkNode = checkNode(check, context, ignoreOptions, otherOptions);
return {
ClassProperty: _checkNode,
TSIndexSignature: _checkNode,
TSPropertySignature: _checkNode
};
}
});
var _a;

@@ -1544,8 +1755,5 @@ /**

_a[name$2] = rule$2,
_a[name$3] = rule$3,
_a[name$4] = rule$4,
_a[name$5] = rule$5,
_a[name$6] = rule$6,
_a[name$c] = rule$c,
_a[name$d] = rule$d,
_a[name$7] = rule$7,

@@ -1555,5 +1763,7 @@ _a[name$8] = rule$8,

_a[name$a] = rule$a,
_a[name$3] = rule$3,
_a[name$b] = rule$b,
_a[name$c] = rule$c,
_a[name$d] = rule$d,
_a[name$e] = rule$e,
_a[name$f] = rule$f,
_a);

@@ -1560,0 +1770,0 @@

{
"name": "eslint-plugin-ts-immutable",
"version": "0.2.1",
"version": "0.3.0",
"description": "ESLint rules to disable mutation in TypeScript.",

@@ -13,3 +13,8 @@ "main": "lib/index.js",

"eslint",
"immutability"
"eslint plugin",
"immutable",
"immutability",
"functional",
"functional programming",
"fp"
],

@@ -58,2 +63,3 @@ "author": "Jonas Kello",

"eslint-plugin-jest": "^22.7.1",
"eslint-plugin-jsdoc": "^15.5.3",
"eslint-plugin-prettier": "^3.1.0",

@@ -63,2 +69,3 @@ "glob": "^7.1.4",

"jest": "^24.8.0",
"json-schema": "^0.2.3",
"lint-staged": "^8.2.1",

@@ -77,7 +84,10 @@ "prettier": "^1.18.2",

"peerDependencies": {
"eslint": ">=6.0.0"
},
"optionalDependencies": {
"eslint": ">=6.0.0",
"typescript": ">=3.4.1"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
},
"scripts": {

@@ -93,3 +103,3 @@ "compile": "rollup -c",

"test-compiled": "USE_COMPLIED=1 yarn test",
"verify": "yarn build && yarn lint && yarn build-tests && yarn test-compiled",
"verify": "yarn build && yarn lint && yarn build-tests && yarn test-compiled && rimraf build",
"report-coverage": "codecov -f coverage/lcov.info",

@@ -96,0 +106,0 @@ "preversion": "yarn verify",

@@ -66,2 +66,3 @@ # eslint-plugin-ts-immutable

`@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".

@@ -71,14 +72,2 @@ ```json

"parser": "@typescript-eslint/parser",
"plugins": ["ts-immutable"],
"rules": {
"ts-immutable/rule-name": "error"
}
}
```
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".
```json
{
"parser": "@typescript-eslint/parser",
"parserOptions": {

@@ -115,25 +104,24 @@ "project": "./tsconfig.json"

| Name | Description | <span title="Recommended">:see_no_evil:</span> | <span title="Functional Lite">:hear_no_evil:</span> | <span title="Functional">:speak_no_evil:</span> | :wrench: | :blue_heart: |
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------- | :--------------------------------------------: | :-------------------------------------------------: | :---------------------------------------------: | :------: | :---------------: |
| [`ts-immutable/readonly-keyword`](./docs/rules/readonly-keyword.md) | Enforce readonly modifiers are used where possible | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :wrench: | :thought_balloon: |
| [`ts-immutable/readonly-array`](./docs/rules/readonly-array.md) | Enforce readonly array over mutable arrays | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :wrench: | :thought_balloon: |
| [`ts-immutable/no-let`](./docs/rules/no-let.md) | Disallow mutable variables | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :wrench: | |
| [`ts-immutable/no-array-mutation`](./docs/rules/no-array-mutation.md) | Disallow mutating arrays | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :thought_balloon: |
| [`ts-immutable/no-object-mutation`](./docs/rules/no-object-mutation.md) | Disallow mutating objects | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :blue_heart: |
| [`ts-immutable/no-method-signature`](./docs/rules/no-method-signature.md) | Enforce property signatures with readonly modifiers over method signatures | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :thought_balloon: |
| [`ts-immutable/no-delete`](./docs/rules/no-delete.md) | Disallow delete expressions | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | |
| Name | Description | <span title="Recommended">:see_no_evil:</span> | <span title="Functional Lite">:hear_no_evil:</span> | <span title="Functional">:speak_no_evil:</span> | :wrench: | :blue_heart: |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------- | :--------------------------------------------: | :-------------------------------------------------: | :---------------------------------------------: | :------: | :---------------: |
| [`prefer-readonly-types`](./docs/rules/prefer-readonly-types.md) | Use readonly types and readonly modifiers where possible | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :wrench: | :thought_balloon: |
| [`no-let`](./docs/rules/no-let.md) | Disallow mutable variables | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | |
| [`immutable-data`](./docs/rules/immutable-data.md) | Disallow mutating objects and arrays | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :blue_heart: |
| [`no-method-signature`](./docs/rules/no-method-signature.md) | Enforce property signatures with readonly modifiers over method signatures | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | :thought_balloon: |
### Functional style rules
| Name | Description | <span title="Recommended">:see_no_evil:</span> | <span title="Functional Lite">:hear_no_evil:</span> | <span title="Functional">:speak_no_evil:</span> | :wrench: | :blue_heart: |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | :--------------------------------------------: | :-------------------------------------------------: | :---------------------------------------------: | :------: | :---------------: |
| [`ts-immutable/no-this`](./docs/rules/no-this.md) | Disallow this access | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`ts-immutable/no-class`](./docs/rules/no-class.md) | Disallow classes | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`ts-immutable/no-mixed-interface`](./docs/rules/no-mixed-interface.md) | Restrict interfaces so that only members of the same kind of are allowed in them | | :heavy_check_mark: | :heavy_check_mark: | | :thought_balloon: |
| [`ts-immutable/no-expression-statement`](./docs/rules/no-expression-statement.md) | Using expressions to cause side-effects not allowed | | | :heavy_check_mark: | | |
| [`ts-immutable/no-if-statement`](./docs/rules/no-if-statement.md) | Disallow if statements | | | :heavy_check_mark: | | |
| [`ts-immutable/no-loop-statement`](./docs/rules/no-loop-statement.md) | Disallow imperative loops | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`ts-immutable/no-throw`](./docs/rules/no-throw.md) | Disallow throwing exceptions | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`ts-immutable/no-try`](./docs/rules/no-try.md) | Disallow try-catch[-finally] and try-finally patterns | | | :heavy_check_mark: | | |
| [`ts-immutable/no-reject`](./docs/rules/no-reject.md) | Disallow rejecting Promises | | | | | |
| Name | Description | <span title="Recommended">:see_no_evil:</span> | <span title="Functional Lite">:hear_no_evil:</span> | <span title="Functional">:speak_no_evil:</span> | :wrench: | :blue_heart: |
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- | :--------------------------------------------: | :-------------------------------------------------: | :---------------------------------------------: | :------: | :---------------: |
| [`no-this`](./docs/rules/no-this.md) | Disallow this access | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`no-class`](./docs/rules/no-class.md) | Disallow classes | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`no-mixed-interface`](./docs/rules/no-mixed-interface.md) | Restrict interfaces so that only members of the same kind are allowed in them | | :heavy_check_mark: | :heavy_check_mark: | | :thought_balloon: |
| [`no-expression-statement`](./docs/rules/no-expression-statement.md) | Disallow expressions to cause side-effects | | | :heavy_check_mark: | | |
| [`no-conditional-statement`](./docs/rules/no-conditional-statement.md) | Disallow conditional statements (if and switch statements) | | | :heavy_check_mark: | | |
| [`no-loop-statement`](./docs/rules/no-loop-statement.md) | Disallow imperative loops | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`no-return-void`](./docs/rules/no-return-void.md) | Disallow function that return nothing | | :heavy_check_mark: | :heavy_check_mark: | | :thought_balloon: |
| [`functional-parameters`](./docs/rules/functional-parameters.md) | Functions must have functional parameter | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`no-throw`](./docs/rules/no-throw.md) | Disallow throwing exceptions | | :heavy_check_mark: | :heavy_check_mark: | | |
| [`no-try`](./docs/rules/no-try.md) | Disallow try-catch[-finally] and try-finally patterns | | | :heavy_check_mark: | | |
| [`no-reject`](./docs/rules/no-reject.md) | Disallow rejecting Promises | | | | | |

@@ -195,3 +183,3 @@ ## Recommended standard rules

[version-image]: https://img.shields.io/npm/v/eslint-plugin-ts-immutable.svg?style=flat
[version-url]: https://www.npmjs.com/packageeslint-plugin-ts-immutable
[version-url]: https://www.npmjs.com/package/eslint-plugin-ts-immutable
[travis-image]: https://travis-ci.com/jonaskello/eslint-plugin-ts-immutable.svg?branch=master&style=flat

@@ -198,0 +186,0 @@ [travis-url]: https://travis-ci.com/jonaskello/eslint-plugin-ts-immutable

Sorry, the diff of this file is not supported yet

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