Naming conventions 3: improving naming quality
This article is Part 3 (the final part) of the three-part series on naming conventions. Building on the basics covered in Part 1: case conventions, variables, and constants and Part 2: Functions and Classes, it covers principles for improving naming quality, a comprehensive exercise, and an overall summary.
Use pronounceable, meaningful names
// ❌ Bad: Abbreviated, unpronounceable
const genYmdhms = (): string => {
const now = new Date();
const pad = (n: number) => String(n).padStart(2, "0");
return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;
};
const dfColor = "#fff";
const usrCnt = 10;
// ✅ Good: Pronounceable with clear meaning
const generateTimestamp = (): string => {
const now = new Date();
const pad = (n: number) => String(n).padStart(2, "0");
return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;
};
const defaultColor = "#fff";
const userCount = 10;
Reasons:
- Easier verbal communication with teammates
- Easier to explain in code reviews
- Easier for new members to understand
Use plural forms for arrays and lists
A variable that represents an array or list is recognizable as an array at a glance when it is plural.
// ❌ Bad: Singular
const user = [{ id: 1 }, { id: 2 }];
const item = ["apple", "banana", "orange"];
user.forEach(u => console.log(u)); // Hard to tell that user is an array
// ✅ Good: Plural
const users = [{ id: 1 }, { id: 2 }];
const items = ["apple", "banana", "orange"];
users.forEach(user => console.log(user)); // Clear that users is the array and user is the element
// ✅ Use plural forms in TypeScript type definitions too
type User = {
id: number;
name: string;
};
type Users = User[];
Irregular plurals
// ✅ Irregular English plurals
const children = [child1, child2]; // child → children
const people = [person1, person2]; // person → people
const mice = [mouse1, mouse2]; // mouse → mice
// ✅ Same singular and plural
const sheep = [sheep1, sheep2]; // sheep → sheep
const fish = [fish1, fish2]; // fish → fish
Unify words with the same meaning
Within a project, unify the words that represent the same concept.
// ❌ Bad: Different words for the same concept
class UserController {
getUser(id: string): User { }
}
class ProductController {
fetchProduct(id: string): Product { } // ❌ get and fetch are mixed
}
class OrderController {
retrieveOrder(id: string): Order { } // ❌ retrieve is mixed in too
}
// ✅ Good: Unified
class UserController {
getUser(id: string): User { }
}
class ProductController {
getProduct(id: string): Product { }
}
class OrderController {
getOrder(id: string): Order { }
}
// ────────────────────────────────────────────
// Other unification examples
// ────────────────────────────────────────────
// ❌ Bad: Multiple words for deletion
function removeUser(id: string) { }
function deleteProduct(id: string) { }
function eraseOrder(id: string) { }
// ✅ Good: Unified on delete
function deleteUser(id: string) { }
function deleteProduct(id: string) { }
function deleteOrder(id: string) { }
Common similar words
Examples of similar words to unify
| Meaning | Candidates |
|---|---|
| Retrieve | get / fetch / retrieve |
| Delete | delete / remove / erase |
| Create | create / make / build |
| Update | update / modify / edit |
| Send | send / submit / post |
| Display | show / display / render |
Recommended approach: Create a glossary for your project and share it across the whole team.
// ✅ A project terminology example (glossary.ts)
/**
* Project glossary
*
* - Retrieve data: get (fetch when asynchronous)
* - Create data: create
* - Update data: update
* - Delete data: delete
* - Display: show
*/
Use contrasting words
For values with opposite meanings, use names that form a contrast.
// ✅ Examples of contrasting words
// start ⇔ end
const startTime = new Date();
const endTime = new Date();
function startTimer() { }
function stopTimer() { } // ✅ start ⇔ stop
// min ⇔ max
const minValue = 0;
const maxValue = 100;
// previous ⇔ next
const previousPage = 1;
const nextPage = 3;
// first ⇔ last
const firstItem = items[0];
const lastItem = items[items.length - 1];
// open ⇔ close
function openModal() { }
function closeModal() { } // ✅ open ⇔ close
// show ⇔ hide
function showElement() { }
function hideElement() { } // ✅ show ⇔ hide
// enable ⇔ disable
function enableFeature() { }
function disableFeature() { } // ✅ enable ⇔ disable
// ❌ Bad: The contrast is unclear
function startProcess() { }
function endProcess() { } // ❌ Don't mix start and end for action functions
// ✅ Good
function startProcess() { }
function stopProcess() { } // ✅ start ⇔ stop
Use different pairs for points in time versus actions: for variables representing a point in time, startTime ⇔ endTime (start ⇔ end) is a natural pair. For functions representing an action, align them as start ⇔ stop or begin ⇔ end. The counterpart of startProcess is stopProcess.
Common contrasting words
List of contrasting words
| Start / action | Opposite |
|---|---|
start | stop (end) |
begin | end (finish) |
open | close |
show | hide |
enable | disable |
activate | deactivate |
lock | unlock |
first | last |
min | max |
previous | next |
increment | decrement |
add | remove |
insert | delete |
push | pop |
acquire | release |
Avoid meaningless words
Generic words like Data, Info, and Manager provide no concrete information on their own. What you should avoid is a name made only of generic words, such as DataManager. When the thing being managed or described is clear, as in SessionManager or FileMetadata, there is no problem.
// ❌ Bad: Manager is too abstract (it's unclear what data it manages)
class DataManager {
processData() { }
}
// ✅ Good: Show the concrete responsibility
class UserRepository {
findById(id: string): User | null { }
save(user: User): void { }
}
// ────────────────────────────────────────────
// ❌ Bad: Object, Thing, and other abstractions
const userObject = { name: "Taro" };
const dataThing = [1, 2, 3];
// ✅ Good
const user = { name: "Taro" };
const numbers = [1, 2, 3];
There are exceptions, though
Some words carry meaning in specific contexts.
// ✅ Acceptable examples
// Metadata: the specific meaning of "data about data"
interface FileMetadata {
size: number;
createdAt: Date;
mimeType: string;
}
// Config/Settings: a conventional name representing configuration
interface AppConfig {
apiUrl: string;
timeout: number;
}
// Context: a convention in frameworks such as React/Angular
const UserContext = React.createContext<User | null>(null);
Abbreviating variable names
Use abbreviations only when they are generally recognized.
// ────────────────────────────────────────────
// ✅ Generally recognized abbreviations
// ────────────────────────────────────────────
// ID (identifier)
const userId = "12345";
const productId = 100;
// URL (Uniform Resource Locator)
const apiUrl = "https://api.example.com";
// HTTP (HyperText Transfer Protocol)
const httpClient = new HttpClient();
// API (Application Programming Interface)
const apiResponse = await fetchData();
// DB (Database)
const dbConnection = createConnection();
// Auth (Authentication)
const authToken = "abc123";
// Config (Configuration)
const appConfig = loadConfig();
// Temp (Temporary)
const tempValue = calculateTemp();
// Max/Min (Maximum/Minimum)
const maxRetries = 3;
const minValue = 0;
// Prev/Next (Previous/Next)
const prevPage = 1;
const nextPage = 3;
// ────────────────────────────────────────────
// ❌ Abbreviations to avoid
// ────────────────────────────────────────────
// ❌ Custom abbreviations
const usrNm = "Taro"; // ✅ userName
const prdLst = []; // ✅ productList
const calcTtl = () => {}; // ✅ calculateTotal
// ❌ Just dropping vowels
const btn = document.querySelector('button'); // ✅ button
const msg = "Hello"; // ✅ message
const err = new Error(); // ✅ error (err is sometimes acceptable)
// ❌ Abbreviations that make no sense without context
const d = new Date(); // ✅ date or currentDate
const i = 0; // ✅ index or count (outside of loops)
const tmp = getValue(); // ✅ temporary or a concrete name
Abbreviating loop variables is acceptable
// ✅ Conventional abbreviations are acceptable in loops
for (let i = 0; i < 10; i++) {
console.log(i);
}
// ✅ Nested loops
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
matrix[i][j] = 0;
}
}
// ✅ When a more meaningful name is preferable
for (let userIndex = 0; userIndex < users.length; userIndex++) {
const user = users[userIndex];
// ...
}
// ✅ Use full names with forEach/map
users.forEach(user => { // ✅ user (not u)
console.log(user.name);
});
Exercise 5: A comprehensive naming exercise
Fix the following code to follow the naming conventions for clean code.
// ❌ Before
const d = new Date();
const usrCnt = 100;
interface prdData {
id: number;
nm: string;
prc: number;
}
class usrMgr {
getUsrInf(id: number) {
// ...
}
delUsr(id: number) {
// ...
}
}
function calcTtl(items: any[]) {
let t = 0;
for (let i = 0; i < items.length; i++) {
t += items[i].prc;
}
return t;
}
const isNotComplete = false;
if (!isNotComplete) {
// ...
}
📝 View answer
// ✅ After
const currentDate = new Date();
const userCount = 100;
interface ProductData {
id: number;
name: string;
price: number;
}
class UserManager {
getUser(id: number) {
// ...
}
deleteUser(id: number): void {
// ...
}
}
function calculateTotal(items: ProductData[]): number {
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price;
}
return total;
}
// Avoid negative forms
const isComplete = true;
if (isComplete) {
// ...
}
calculateTotal also has an alternative using reduce.
function calculateTotal(items: ProductData[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
Key fixes:
d→currentDate: clarify the meaningusrCnt→userCount: avoid abbreviationprdData→ProductData: PascalCasenm→name,prc→price: full wordsusrMgr→UserManager: PascalCasegetUsrInf→getUser: use full words and remove the redundant "Info"delUsr→deleteUser: full word + unified verbcalcTtl→calculateTotal: full wordst→total: a meaningful nameisNotComplete→isComplete: avoid the negative form
Summary of naming conventions
Naming conventions quick reference
| Target | Rule | Example |
|---|---|---|
| Variable | camelCase | userName, itemCount |
| Constant | UPPER_SNAKE_CASE | MAX_COUNT |
| Function | camelCase | getUserById |
| Class | PascalCase | UserService |
| Interface | PascalCase | UserProfile |
| Type alias | PascalCase | UserId |
| Enum | PascalCase | UserRole |
| Boolean | is / has / can / should + state/ability | isValid, canEdit |
| Array | Plural | users, items |
- Use names with clear intent
- Use searchable names
- Maintain consistency
- Reduce the reader's cognitive load