Abbreviation Restrictions
Automatically enforces descriptive naming by banning common abbreviations and anti-patterns.
Overview
This feature prevents usage of common abbreviations that reduce code readability. It's based on a comprehensive deny-list of anti-patterns, while allowing well-established technical terms and framework conventions through an allow-list.
Selector: variable (all types including const global), function, parameter, memberLike (class members)
Applied: Lowest precedence (catch-all safety net)
TIP
Abbreviation restrictions apply to all identifiers, including:
- Local variables
- Global const variables (module-level constants)
- Function parameters
- Function names
- Class members (public, private, protected, static, readonly)
Why This Rule
Single-letter names and ambiguous abbreviations are among the most common sources of confusion in codebases:
- Single-letter variables → Banned except for coordinates (
x,y,z)i/j/k→ Useindex,rowIndex,colIndexinsteade→ Useerror,event, orelementdepending on contexts→ Usestring,source, orstatusdepending on contextn→ Usecount,length, ornumberdepending on context- Only exception:
x,y,zare allowed for coordinate systems and geometry
- Ambiguous abbreviations → Use full descriptive names
data/info/obj→ What kind of data? UseresponseBody,metadata,userPayload,payloadres/req→ Acceptable in Express handlers, but ambiguous elsewhere (result? resource? response?)err→ Useerror- it's only 2 more charactersdata→ Too vague - use specific terms likepayload,result,records,responseBody,input,output
Philosophy
This rule embodies the principle: "Write code for humans first, computers second."
Clear names:
- Reduce onboarding time for new team members
- Make code self-documenting
- Prevent bugs from misunderstanding
- Eliminate the need for guessing in code reviews
How It Works
The rule uses two lists:
DENY_LIST
Contains ~140+ common abbreviations and their recommended replacements:
{
str: ['string', 'text'],
num: ['number', 'amount', 'count'],
arr: ['array', 'list', 'items'],
obj: ['object', 'entity', 'payload'],
data: ['payload', 'result', 'records', 'responseBody'],
// ... and many more
}ALLOW_LIST
Contains widely-recognized technical terms that are acceptable:
['id', 'url', 'api', 'ui', 'db', 'json', 'html', 'uuid', 'jwt', 'ip', 'http', ...]✅ Good
// Valid names that avoid abbreviations from the DENY_LIST
function abbreviationsPositiveExample() {
// Variables - full descriptive names
const userData = { id: 1, name: 'Alice' }; // ✅ id is in ALLOW_LIST
const apiUrl = 'https://example.com'; // ✅ api, url in ALLOW_LIST
const userCount = 10; // ✅ not abbreviated
const responseBody = { status: 'ok' }; // ✅ instead of "res"
const errorMessage = 'Failed'; // ✅ instead of "err"
const callback = () => {}; // ✅ instead of "cb"
const element = document.createElement('div'); // ✅ instead of "el"
const button = document.createElement('button'); // ✅ instead of "btn"
const directory = '/home/user'; // ✅ instead of "dir"
const filePath = '/home/user/file.txt'; // ✅ instead of "fpath"
const configuration = { debug: true }; // ✅ instead of "cfg"
const timestamp = Date.now(); // ✅ instead of "ts"
const message = 'Hello'; // ✅ instead of "msg"
const minimum = 0; // ✅ instead of "min"
const maximum = 100; // ✅ instead of "max"
const index = 0; // ✅ instead of "i", "j", "k", or "idx"
const itemIndex = 1; // ✅ instead of "i"
const rowIndex = 2; // ✅ instead of "j"
// Single-letter coordinates are allowed (x, y, z)
const x = 10; // ✅ allowed for coordinates
const y = 20; // ✅ allowed for coordinates
const z = 30; // ✅ allowed for 3D coordinates
return {
userData,
apiUrl,
userCount,
responseBody,
errorMessage,
callback,
element,
button,
directory,
filePath,
configuration,
timestamp,
message,
minimum,
maximum,
index,
itemIndex,
rowIndex,
x,
y,
z,
};
}
// Functions - descriptive names
function processUserData() {} // ✅
function handleErrorMessage() {} // ✅
function formatTimestamp() {} // ✅
function validateDirectory() {} // ✅
// Parameters - descriptive names
function processRequest(requestData: unknown, onComplete: () => void) {
// ✅
return { requestData, onComplete };
}
function handleResponse(responseData: unknown, metadata: unknown) {
// ✅
return { responseData, metadata };
}❌ Bad
// Invalid names that use banned abbreviations from DENY_LIST
// Global variables - banned abbreviations
export const msg = 'Hello'; // ❌ should be: message
const cfg = {}; // ❌ should be: config or configuration
function abbreviationsNegativeExample() {
// Single-letter variables (except x, y, z) - all banned
const a = [1, 2, 3]; // ❌ should be: array, items, values, etc.
const b = true; // ❌ should be: boolean, isEnabled, flag, etc.
const c = 'character'; // ❌ should be: character, count, class, etc.
const d = { key: 'value' }; // ❌ should be: data, payload, etc.
const e = new Error(); // ❌ should be: error, exception, event
const f = () => {}; // ❌ should be: function, callback, handler
const i = 0; // ❌ should be: index, itemIndex, rowIndex
const j = 1; // ❌ should be: index, itemIndex, rowIndex
const k = 2; // ❌ should be: index, key, keyIndex
const n = 10; // ❌ should be: count, number, length
const p = { x: 0, y: 0 }; // ❌ should be: point, position, parameter
const s = 'text'; // ❌ should be: string, text, value
const t = Date.now(); // ❌ should be: time, timestamp, token
// Variables - banned abbreviations
const str = 'text'; // ❌ should be: string or text
const num = 42; // ❌ should be: number or count
const arr = [1, 2, 3]; // ❌ should be: array or items
const obj = { key: 'value' }; // ❌ should be: object or specific domain name
const fn = () => {}; // ❌ should be: function or callback
const cb = () => {}; // ❌ should be: callback or onComplete
const err = new Error(); // ❌ should be: error
const tmp = 'temp'; // ❌ should be: temporary or tempValue
// NOTE: 'data', 'min', 'max' are in ALLOW_LIST, so they are not tested here
const info = {}; // ❌ should be: metadata or details
const val = 42; // ❌ should be: value
const idx = 0; // ❌ should be: index
const cnt = 5; // ❌ should be: count
const len = 10; // ❌ should be: length
const dir = '/path'; // ❌ should be: directory or direction
const btn = null; // ❌ should be: button
const el = null; // ❌ should be: element
const img = null; // ❌ should be: image
return {
a,
b,
c,
d,
e,
f,
i,
j,
k,
n,
p,
s,
t,
str,
num,
arr,
obj,
fn,
cb,
err,
tmp,
info,
val,
idx,
cnt,
len,
dir,
btn,
el,
img,
};
}
// Functions - banned abbreviations
function processStr() {} // ❌ should be: processString
function handleErr() {} // ❌ should be: handleError
function formatMsg() {} // ❌ should be: formatMessage
function validateCfg() {} // ❌ should be: validateConfig
// Parameters - banned abbreviations
function processReq(req: unknown, res: unknown) {
// ❌ req and res should be: request and response (unless in framework context)
return { req, res };
}
function handleData(data: unknown, info: unknown) {
// ❌ data should be more specific: payload, result, records, etc.
// ❌ info should be more specific: metadata, details, etc.
return { data, info };
}Customization
You can customize the lists for your project:
// eslint.config.js
import { ALLOW_LIST, DENY_LIST } from 'eslint-config-naming';
// Add your own allowed abbreviations
const myAllowList = [...ALLOW_LIST, 'req', 'res', 'ctx'];
// Or remove some from deny list for your use case
const myDenyList = { ...DENY_LIST };
delete myDenyList.req;
delete myDenyList.res;
// Then build your own custom regex using these lists
const bannedNames = Object.keys(myDenyList)
.filter((name) => !myAllowList.includes(name))
.map((s) => s.replaceAll(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.join('|');
// Use in your custom naming-convention rule
export default [
{
rules: {
'@typescript-eslint/naming-convention': [
'error',
// ... your other rules
{
selector: 'variable',
format: null,
custom: { regex: `^(${bannedNames})$`, match: false },
},
],
},
},
];Common Exceptions
Framework Parameters
In Express.js, Koa, or similar frameworks, req, res, ctx, next are idiomatic:
// Acceptable in framework context
app.get('/users', (req, res, next) => {
// This is the established convention
});By default, these are allowed when used as parameters due to rule precedence. If your project uses them heavily, consider adding them to your custom allow-list.
Loop Indices
Single-letter loop variables like i, j, k are banned. Use descriptive names instead:
// ❌ Bad - single-letter loop variables
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
}
// ✅ Better - use array iteration methods
for (const item of items) {
console.log(item);
}
// ✅ Good - descriptive name when index is needed
items.forEach((item, itemIndex) => {
console.log(itemIndex, item);
});
// ✅ Good - descriptive names in traditional loops
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
for (let colIndex = 0; colIndex < cols.length; colIndex++) {
// Clear which dimension each index represents
}
}Technical Initialisms
Well-known technical terms are allowed:
const userId = 123; // ✅ 'id' is in ALLOW_LIST
const apiUrl = 'https://api.example.com'; // ✅ 'api' and 'url' are allowed
const jsonData = JSON.parse(response); // ✅ 'json' is allowed
const jwtToken = auth.getToken(); // ✅ 'jwt' is allowed🚫 Deny List
/**
* DENY_LIST:
* key = abbreviation / anti-pattern identifier you want to forbid
* value = allowed replacements (full names or clearer alternatives)
*/
export const DENY_LIST: Readonly<Record<string, readonly string[]>> = {
// Single-letter / too short (x, y, z are allowed for coordinates)
a: ['array', 'attribute', 'value', 'accumulator'],
b: ['boolean', 'buffer', 'byte', 'value'],
c: ['character', 'count', 'class', 'component'],
d: ['data', 'day', 'distance', 'delta'],
e: ['event', 'error', 'exception', 'element'],
f: ['function', 'field', 'flag', 'file'],
g: ['group', 'global', 'get'],
h: ['height', 'handler', 'hash', 'header'],
i: ['index', 'itemIndex', 'rowIndex', 'columnIndex'],
j: ['index', 'itemIndex', 'rowIndex', 'columnIndex'],
k: ['index', 'key', 'keyIndex'],
l: ['length', 'list', 'line', 'label'],
m: ['map', 'message', 'method', 'model'],
n: ['count', 'length', 'number', 'node'],
o: ['object', 'option', 'output'],
p: ['parameter', 'property', 'position', 'point'],
q: ['query', 'queue', 'question'],
r: ['result', 'response', 'record', 'row'],
s: ['string', 'source', 'state', 'status'],
t: ['type', 'time', 'token', 'text'],
u: ['user', 'url', 'unit', 'update'],
v: ['value', 'variable', 'version'],
w: ['width', 'window', 'wrapper'],
// x, y, z are allowed in ALLOW_LIST for coordinate systems
// Core types / primitives
str: ['string', 'text'],
num: ['number', 'amount', 'count'],
bool: ['boolean', 'isEnabled', 'hasValue'],
fn: ['function', 'handler', 'callback'],
cb: ['callback', 'onComplete', 'onSuccess', 'onError'],
// Generic “intent-hiding” names (common anti-patterns)
data: ['payload', 'result', 'records', 'responseBody', 'input', 'output'],
info: ['metadata', 'details', 'summary', 'diagnostics'],
obj: ['object', 'entity', 'model', 'payload'], // or ideally: rename to the real domain noun
val: ['value', 'result', 'item', 'entry'],
tmp: ['temporary', 'tempValue', 'scratch'],
temp: ['temporary', 'tempValue', 'scratch'],
misc: ['other', 'fallback', 'unknown'],
stuff: ['items', 'things', 'resources'],
// Collections / data structures
arr: ['array', 'list', 'items', 'elements'],
lst: ['list', 'items', 'values'],
coll: ['collection', 'items', 'elements'],
dict: ['dictionary', 'map'],
kv: ['keyValue', 'keyValuePair'],
idx: ['index', 'itemIndex'],
cnt: ['count', 'total', 'quantity'],
qty: ['quantity', 'count', 'amount'],
len: ['length'],
max: ['maximum', 'upperBound'],
min: ['minimum', 'lowerBound'],
// Strings / formats
fmt: ['format', 'formatter'],
tpl: ['template'],
tmpl: ['template'],
re: ['regex', 'pattern'],
regex: ['regularExpression', 'pattern'], // if you want to enforce full wording
md: ['markdown'],
csv: ['commaSeparatedValues'],
tsv: ['tabSeparatedValues'],
// Time
dt: ['dateTime', 'date'],
ts: ['timestamp'],
ms: ['milliseconds'],
sec: ['seconds'],
mins: ['minutes'],
hrs: ['hours'],
dur: ['duration'],
ttl: ['timeToLive', 'cacheTtl'],
eta: ['estimatedTimeOfArrival', 'estimatedDuration'],
// Filesystem / paths
dir: ['directory', 'direction'], // ambiguous by design — choose meaning
cwd: ['currentWorkingDirectory'],
fname: ['fileName'],
fpath: ['filePath'],
ext: ['extension', 'fileExtension'],
buf: ['buffer'],
cfg: ['config', 'configuration'],
conf: ['config', 'configuration'],
// Web / networking (common ambiguous ones)
req: ['request'],
res: ['response', 'result', 'resource'], // ambiguous outside frameworks
resp: ['response'],
hdr: ['header'],
hdrs: ['headers'],
qs: ['queryString'],
urlStr: ['url', 'urlString'],
uriStr: ['uri', 'uriString'],
// Auth/security ambiguous
auth: ['authentication', 'authorization'], // pick one
authn: ['authentication'],
authz: ['authorization'],
cred: ['credential'],
creds: ['credentials'],
tok: ['token'],
jwtStr: ['jwt', 'jwtToken'],
// Architecture / layers
svc: ['service'],
ctrl: ['controller'],
mgr: ['manager'],
repo: ['repository'],
util: ['utility', 'helpers'],
impl: ['implementation'],
// UI / DOM
el: ['element'],
elem: ['element'],
evt: ['event'],
btn: ['button'],
lbl: ['label'],
img: ['image'],
nav: ['navigation'],
dlg: ['dialog'],
notif: ['notification'],
// Business-ish (often seen, often unclear)
usr: ['user'],
acct: ['account'],
addr: ['address'],
amt: ['amount'],
bal: ['balance'],
inv: ['invoice', 'inventory'], // ambiguous
// Database-ish
dbConn: ['databaseConnection'],
txn: ['transaction'],
tx: ['transaction'],
tbl: ['table'],
col: ['column'],
rec: ['record'],
recs: ['records'],
ver: ['version'],
rev: ['revision'],
// Observability
dbg: ['debug', 'debugInfo'],
msg: ['message'],
err: ['error'], // if you want “error” only; remove if you want to allow err
} as const;✅ Allow List
/**
* ALLOW_LIST:
* Identifiers allowed “as-is” because they are widely-recognized initialisms,
* ecosystem conventions, or required by external APIs/frameworks.
*
* Recommendation: In your ESLint rule, allow some of these ONLY in specific contexts:
* - function params: req, res, ctx, next
* - well-known technical initialisms: id, url, api, ui, db, json, html, css, uuid, jwt
*/
export const ALLOW_LIST: readonly string[] = [
// Very common initialisms / ubiquitous
'id',
'ids',
'url',
'urls',
'uri',
'uris',
'api',
'ui',
'ux',
'db',
'sql',
'json',
'yaml',
'yml',
'html',
'css',
'uuid',
'jwt',
'ip',
'dns',
'http',
'https',
'min',
'max',
'md',
'csv',
'tsv',
'ts', // false positive for TypeScript files
'ms',
'regex',
'repo',
// Node / platform conventions
'fs', // Node.js "fs" module is standard
// Framework-idiomatic params (consider allowing only as parameters)
// 'req',
// 'res',
// 'ctx',
'next',
// Single-letter coordinate variables (allowed for geometry/render contexts)
'x',
'y',
'z',
] as const;For the complete DENY_LIST and ALLOW_LIST, see:
- src/naming-abbreviations.ts in the repository