@coderrob/eslint-plugin-zero-tolerance
v1.2.4
Published
Strict, opinionated ESLint rules for TypeScript — enforcing type safety, code quality, testing standards, and maintainable patterns with zero exceptions.
Maintainers
Readme
@coderrob/eslint-plugin-zero-tolerance
Strict, opinionated ESLint plugin for TypeScript that enforces type safety, code quality, testing standards, and maintainable patterns — with zero exceptions.
Features
- 69 custom ESLint rules across eight categories: type safety, code quality, testing, imports, error handling, bug prevention, naming conventions, and documentation
- Two presets —
recommended(warn severity for gradual adoption) andstrict(error severity for full enforcement) - ESLint 8.57+, 9.x, and 10.x — flat config and legacy
.eslintrcboth supported - 99%+ test coverage — every rule is thoroughly tested with both valid and invalid cases
- Built with
@typescript-eslint/utilsfor full TypeScript AST support
Requirements
- Node.js
17 when using ESLint 8.57.0+ or 9.x
19 when using ESLint 10.x
- ESLint 8.57.0+, 9.x, or 10.x
@typescript-eslint/parser8.x- TypeScript 5.x
Installation
npm install --save-dev @coderrob/eslint-plugin-zero-tolerance @typescript-eslint/parserQuick Start
ESLint 9+ (Flat Config)
// eslint.config.js
import zeroTolerance from '@coderrob/eslint-plugin-zero-tolerance';
export default [zeroTolerance.configs.recommended];ESLint 8.x (Legacy Config)
// .eslintrc.js
module.exports = {
plugins: ['zero-tolerance'],
extends: ['plugin:zero-tolerance/legacy-recommended'],
};Custom Rule Selection
// eslint.config.js
import zeroTolerance from '@coderrob/eslint-plugin-zero-tolerance';
export default [
{
plugins: {
'zero-tolerance': zeroTolerance,
},
rules: {
'zero-tolerance/require-interface-prefix': 'error',
'zero-tolerance/no-throw-literal': 'error',
'zero-tolerance/max-function-lines': ['warn', { max: 40 }],
},
},
];Presets
| Preset | Severity | Config Key |
| ------------------ | -------- | --------------------- |
| Recommended | warn | configs.recommended |
| Strict | error | configs.strict |
| Legacy Recommended | warn | legacy-recommended |
| Legacy Strict | error | legacy-strict |
Rules
Naming Conventions
| Rule | Description |
| -------------------------- | -------------------------------------------------------------------------------------- |
| require-interface-prefix | Enforce that TypeScript interface names start with I followed by an uppercase letter |
Documentation
| Rule | Description |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| require-bdd-spec | Enforce that every TypeScript source file has a valid sibling .ts.bdd.json BDD spec |
| require-jsdoc-anonymous-functions | Require JSDoc comments on anonymous function-like constructs except test files and known test callbacks |
| require-jsdoc-functions | Require JSDoc comments on named functions (except test files) |
| require-optional-chaining | Require optional chaining instead of repeated guard access |
| require-readonly-props | Require JSX component props to be typed as readonly |
Testing
| Rule | Description |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| require-test-description-style | Enforce that test descriptions start with should |
| no-jest-have-been-called | Prohibit imprecise call-assertion matchers; use toHaveBeenCalledTimes and toHaveBeenNthCalledWith instead |
| no-mock-implementation | Prohibit persistent mock methods; use Once variants to prevent test bleeds |
| no-set-timeout-in-tests | Disallow setTimeout usage in test files |
| no-set-interval-in-tests | Disallow setInterval usage in test files |
| no-fetch-in-tests | Disallow fetch usage in test files |
| no-restricted-imports-in-tests | Disallow configured dependency imports in test files |
| no-test-interface-declaration | Disallow interface declarations in test files; import production types instead |
Type Safety
| Rule | Description |
| ---------------------------------------- | ---------------------------------------------------------------------------------- |
| no-type-assertion | Prevent use of TypeScript as and angle-bracket assertions |
| no-non-null-assertion | Disallow non-null assertions using the ! postfix operator |
| no-explicit-any | Disallow explicit any; require precise modeling or explicit narrowing |
| no-indexed-access-types | Disallow TypeScript indexed access types |
| no-literal-unions | Ban literal union types in favour of enums |
| no-literal-property-unions | Require property literal unions to use named domain types |
| require-union-type-alias | Require inline union types with multiple type references to use named type aliases |
| no-inline-type-import | Disallow inline import("...").Type annotations |
| no-return-type | Disallow TypeScript ReturnType utility usage |
| no-destructured-parameter-type-literal | Disallow inline object type literals on destructured parameters |
| require-exported-object-type | Require exported object constants to declare an explicit type annotation |
Code Quality
| Rule | Description |
| ---------------------------- | --------------------------------------------------------------------------------------- |
| max-function-lines | Enforce a maximum number of lines per function body |
| max-params | Enforce a maximum number of function parameters |
| no-array-mutation | Disallow mutating array methods |
| no-date-now | Disallow Date.now() and no-arg new Date() usage |
| no-magic-numbers | Disallow magic numbers; use named constants instead |
| no-magic-strings | Disallow magic strings in comparisons and switch cases |
| no-map-set-mutation | Disallow direct Map and Set mutation methods |
| no-object-mutation | Disallow direct object-property mutation |
| sort-imports | Require import declarations to be ordered by group and alphabetically within each group |
| sort-functions | Require top-level functions and const function expressions to be sorted alphabetically |
| prefer-nullish-coalescing | Prefer nullish coalescing instead of repeated nullish guard ternaries |
| prefer-object-spread | Enforce object spread syntax instead of Object.assign with an empty object literal |
| prefer-readonly-parameters | Prefer readonly typing for object and array-like parameters |
| prefer-string-raw | Prefer String.raw for strings containing escaped backslashes |
| prefer-structured-clone | Prefer structuredClone(...) over JSON.parse(JSON.stringify(...)) for deep cloning |
Error Handling
| Rule | Description |
| ---------------------- | -------------------------------------------------------------------------------------- |
| no-empty-catch | Disallow empty catch blocks that silently swallow errors |
| no-throw-literal | Disallow throwing literals, objects, or templates; always throw a new Error instance |
| prefer-result-return | Prefer returning Result-style values instead of throwing |
Imports
no-parent-internal-access remains opt-in and only matches the first concrete directory reached after .. traversal, such as ../src/foo.
| Rule | Description |
| --------------------------- | --------------------------------------------------------------------------------- |
| require-clean-barrel | Require barrel files (index.*) to contain only module re-exports |
| require-barrel-relative-exports | Require barrel re-exports to use ./ descendant paths |
| no-barrel-parent-imports | Disallow parent-directory traversal in barrel-file import paths |
| no-parent-internal-access | Disallow parent-relative access into protected internal directories such as src |
| no-dynamic-import | Ban dynamic import() and require() outside test files |
| no-export-alias | Prevent use of aliases in export statements |
| no-re-export | Disallow direct or pass-through re-exports from parent/grandparent modules |
| require-node-protocol | Require Node.js built-in module imports to use the node: protocol prefix |
Bug Prevention
| Rule | Description |
| ------------------------------- | ---------------------------------------------------------------------------- |
| no-identical-expressions | Disallow identical expressions on both sides of a binary or logical operator |
| no-identical-branches | Disallow identical conditional branches |
| no-boolean-return-trap | Disallow ambiguous boolean-return APIs outside predicate naming |
| no-redundant-boolean | Disallow redundant comparisons to boolean literals |
| no-for-in | Disallow for..in loops |
| no-labels | Disallow labeled statements |
| no-with | Disallow with statements |
| no-await-in-loop | Disallow await inside loops; use Promise.all() instead |
| no-floating-promises | Disallow unhandled promise expressions; require explicit handling |
| no-math-random | Disallow Math.random(); inject a random source instead |
| no-eslint-disable | Prevent use of eslint-disable comments |
| no-parameter-reassign | Disallow reassigning function parameters |
| no-process-env-outside-config | Disallow process.env reads outside configuration modules |
| no-flag-argument | Disallow boolean flag parameters in function signatures |
| prefer-guard-clauses | Prefer guard clauses by removing else blocks after terminating if branches |
| prefer-shortcut-return | Prefer shortcut boolean returns over if branches that return true/false |
| no-query-side-effects | Disallow side effects in query-style functions |
| require-exhaustive-switch | Require exhaustive switch statements over finite discriminant types |
Documentation
Full rule documentation with examples is available at:
https://coderrob.github.io/eslint-config-zero-tolerance/
License
Apache 2.0 Copyright Robert Lindley
