eslint-config-naming
v1.8.0
Published
Opinionated ESLint naming convention config for TypeScript projects
Downloads
658
Maintainers
Readme
Why
Naming conventions in software development offer numerous benefits:
- Readability: Consistent naming makes code easier to read and understand, reducing cognitive load when scanning files.
- Maintainability: Enforces best practices, improving code quality and consistency across the codebase.
- Code Review and Collaboration: Eliminates debates on naming styles, allowing reviewers to focus on logic and speeding up the process.
- Code Uniformity: Uniform naming promotes collective code ownership, as code looks the same regardless of who wrote it.
- Aesthetics: Provides functional benefits and aesthetic appeal, with a visually pleasing and harmonious structure.
This config makes naming predictable and review-friendly by enforcing a coherent set of rules that scale well across:
- Apps and Libraries
- Frontend and Backend
- Monorepos and Multi-team codebases
It is intentionally BYO parser setup — it ships rules only and does not assume your repo layout or parserOptions.project.
Documentation
Comprehensive documentation with detailed rule explanations and examples is available at drsmile444.github.io/eslint-config-naming.
Key resources:
- Getting Started Guide — Installation and configuration
- Rule Matrix — Complete rule matrix with examples
- Changelog — Version history and updates
At a Glance
This configuration enforces consistent naming patterns across TypeScript constructs:
| Category | Enforced Style | Example |
| ----------------------------- | ----------------------------------------------- | ---------------------------------- |
| Types | PascalCase, no I/T prefixes | ApiResponse, UserData |
| Classes | PascalCase | HttpClient, DataService |
| Interfaces | PascalCase | Config, Options |
| Enums | PascalCase (name), UPPER_CASE (members) | enum Status { ACTIVE, INACTIVE } |
| Variables | camelCase or UPPER_CASE | userName, MAX_RETRIES |
| Booleans | Prefixed with is\|should\|has\|can\|did\|will | isValid, hasAccess |
| Functions | camelCase | calculateTotal(), fetchData() |
| Class Members (public) | camelCase or snake_case | userCount, api_key |
| Class Members (protected) | camelCase (no underscore) | internalState |
| Generic Types | Single letter or T-prefixed | T, TData, TKey |
Abbreviations and single-letter variables are restricted — only x, y, z are allowed for coordinates. Descriptive names like errorMessage and index are enforced over vague shortcuts like err, str, or i.
Code Examples
// Type prefixes
interface IApiResponse {}
type TUserData = {};
// Wrong casing
enum status {
active,
inactive,
}
class userService {}
// Variables
const Myvariable = 'value';
const my_constant = 'constant';
const ready = true;
// Abbreviations
const str = 'message';
// Generics
type Cache<Key, val> = Map<Key, val>;// Clean type names
interface ApiResponse {}
type UserData = {};
// Proper casing
enum Status {
ACTIVE,
INACTIVE,
}
class UserService {}
// Variables
const myVariable = 'value';
const MY_CONSTANT = 'constant';
const isReady = true;
// Descriptive names
const message = 'message';
// Proper generics
type Cache<TKey, TValue> = Map<TKey, TValue>;Note: This is a high-level overview and most rules have additional conditions and exceptions. See the Rule Matrix for complete details and examples.
Installation
1. Install peer dependencies
npm i -D eslint typescript typescript-eslint2. Install this config
npm i -D eslint-config-namingFor other installation options, see Flat Config Usage.
Usage
Option A: Flat Config (ESLint v9+)
// eslint.config.js
import tseslint from 'typescript-eslint';
import namingConfig from 'eslint-config-naming';
export default [
// Your TS wiring (BYO parserOptions)
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
project: ['./tsconfig.json'],
tsconfigRootDir: import.meta.dirname,
},
},
plugins: {
'@typescript-eslint': tseslint.plugin,
},
},
// Naming rules
...namingConfig,
];Option B: Legacy .eslintrc.*
Use the legacy shareable entry:
eslint-config-naming/legacy
// .eslintrc.cjs
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: ['eslint-config-naming/legacy'],
parserOptions: {
project: './tsconfig.json',
},
};How it’s structured
Internally, the config is built as a set of small rule fragments grouped by selector:
memberLikerules (public/private/protected/static/readonly)variablesrules (default, const/global, destructured, boolean prefixes, *Component)typesrules (class, interface, enum, typeLike, enumMember, generics)parametersrules (base, destructured)functionsrules (including final camelCase enforcement)- quoted-key escape hatch (
requiresQuotes→ ignored)
They are combined in a single @typescript-eslint/naming-convention rule entry list, preserving precedence.
Rule overview
This is a quick “what it enforces” list. For full details (and good/bad examples), check the Rule Matrix..
Types
class: PascalCaseinterface: PascalCase and forbidsI*/T*prefixestypeAlias: PascalCase and forbidsI*/T*prefixestypeParameter: Single uppercase letters (T,U,V,K) or prefixed descriptive names (TData,KKey,VValue) or numeric subscripts (T1,T2,K1, etc.)enum: PascalCase, forbids plural-ish names (likeStatuses) andI*/T*enumMember: UPPER_CASE
Members (memberLike)
public static: camelCase, PascalCase or UPPER_CASEprivate static: camelCase, PascalCase or UPPER_CASE, no leading_readonly: UPPER_CASE, camelCase, or snake_casepublic: camelCase or snake_caseprivate: camelCase, no leading_private readonly: camelCase or UPPER_CASE, no leading_protected: camelCase, no leading_
Variables
- default: camelCase or UPPER_CASE, abbreviation restrictions apply
const+global: allows PascalCase (in addition to camelCase/UPPER_CASE), abbreviation restrictions apply- destructured: allows PascalCase, camelCase, snake_case
- booleans: camelCase with required prefix
is|are|should|has|can|did|will - destructured booleans: no prefix requirement (interop friendly)
*Component: allows PascalCase if variable name ends withComponent
Parameters
- default: camelCase, abbreviation restrictions apply
- destructured: allows PascalCase, camelCase, snake_case
Functions
- exported/global: camelCase or PascalCase, abbreviation restrictions apply
- default (catch-all): camelCase, abbreviation restrictions apply
Object Literals
objectLiteralProperty: camelCase, snake_case, PascalCase, or UPPER_CASE (flexible to support various use cases including constant objects)
Quoted members
If a name requires quotes (e.g. HTTP headers, data contracts), it's ignored.
Abbreviation Restrictions
Automatically bans common abbreviations and anti-patterns:
- Single-letter names:
i,j,k,e→ useindex,itemIndex,error - Vague abbreviations:
str,num,arr,obj→ usestring,number,array,object - Intent-hiding names:
data,info,tmp→ usepayload,metadata,temporary - Ambiguous abbreviations:
res,req,dir,cfg→ useresponse,request,directory,config
Well-known technical terms like id, url, api, json, html, uuid are allowed.
See Abbreviation Restrictions docs for the complete list and customization options.
Update policy
This project treats rule and packaging changes as user-facing. Before submitting a change that affects rules, exports, or packaging, please follow the project's update policy (full text in Update Policy Docs). In short, every rule-related change must include:
- Source changes (
src/) implementing the rule or selector. - Tests (
tests/) covering both accepted and rejected examples. - Snippets (
tests/snippets/...) for positive/negative cases where applicable. - Documentation updates in
docs/explaining the rule and examples. - README updates if usage or exports change.
- Package metadata changes (
package.json) such as version bump and export adjustments.
See docs/policies/update-policy.md for the complete checklist, versioning rules, and CI expectations.
License
MIT © 2025-Present Dmytro Vakulenko 🇺🇦
