DEV Community

Andriy Ovcharov
Andriy Ovcharov

Posted on

Naming Conventions in JavaScript (Classes, Components, Events, APIs)

knight with a sword

When you first look at this code, what do you think?

const x = fetch('/getData', { id: d });  
Enter fullscreen mode Exit fullscreen mode

Questions flood your mind:

  • What’s x? An array? An object?

  • Is d a user ID, a timestamp, or something else?

  • Why getData instead of user-profiles?

And indeed. What did the author want to write?

In a series of publications about naming in JavaScript, I will try to propose what I believe to be the correct approach to naming language entities.

Bad naming costs time. A study found developers spend 60% of their time reading code. Poor names make this even harder.

In this guide, we’ll focus on naming conventions for:

  • Classes & Components (UserService vs userService)

  • Events (onClick vs handleClick)

  • API Endpoints (/orders vs /getOrders)

  • Tests (describe('User') vs describe('Test User'))

// πŸ‘ Clear  
class PaymentGateway {  
  processTransaction() { ... }  
}  

// πŸ‘Ž Confusing  
class pg {  
  pt() { ... }  // "pt" = ?  
}  
Enter fullscreen mode Exit fullscreen mode

This isn’t just about style. It’s about:

  • Onboarding (new devs understand your code faster).

  • Maintainability (you’ll thank yourself later).

  • Communication (names should "document" the code).

In a series of publications, we will talk about:

  1. "Naming Conventions in JavaScript (Classes, Components, Events, APIs)"
  2. "JavaScript Variable Naming: Rules You Can’t Ignore"
  3. "How to Name Functions in JavaScript: A Practical Guide"

Ready to name like a pro? Let’s dive in!


πŸ“Œ 1. Class Names (PascalCase)
Classes should be nouns representing entities (objects, services, models) and always start with a capital letter and use PascalCase:

// πŸ‘ Good  
class User { ... }  
class PaymentService { ... }  
class HttpClient { ... }  

// πŸ‘Ž Bad  
class user { ... }       // Lowercase  
class makePayment { ... } // Verb (a class is not a function) 
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 2. Specificity instead of general terms in classes
Avoid names like Manager, Helper, Processor:

/* πŸ‘ Good */  
class UserRepository {}  // Clear: works with user data 
class EmailValidator {}  // Specific goal 

/* πŸ‘Ž Bad */  
class DataManager {}     // What exactly is "managing"?  
class ApiHelper {}       // Too vague
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 3. Components (React/Vue/Svelte)
Component names use PascalCase, like classes:

// πŸ‘ Good  
function UserProfile() { ... }  
class CartItem extends React.Component { ... }  

// πŸ‘Ž Bad  
function userProfile() { ... } // camelCase for components is confusing  
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 4. Events (Event Naming)

  • Handlers: on{Event} (e.g., onClick).

  • Custom events: kebab-case (e.g., user-registered).

// πŸ‘ Good  
button.addEventListener('click', onClick);  
emitter.emit('user-registered', data);  

// πŸ‘Ž Bad  
button.addEventListener('click', handleClick); // Non-standard prefix  
emitter.emit('userRegistered', data); // camelCase for events is non-standard  
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 5. API Endpoints (kebab-case or snake_case)

// πŸ‘ Good  
fetch('/api/user-profiles/123');  
fetch('/api/orders?status=completed');  

// πŸ‘Ž Bad  
fetch('/api/getUserProfile/123'); // Redundant verbs  
fetch('/api/userProfiles');       // camelCase in URLs  
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 6. Tests (describe/it Style)
Test names should describe what is being tested:

// πŸ‘ Good  
describe('UserService', () => {  
  it('should create a new user', () => { ... });  
});  

// πŸ‘Ž Bad  
describe('Test User', () => {  // Vague  
  it('test #1', () => { ... }); // Meaningless  
});  
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 7. Imports (Readability & Context)
Module names should reflect their purpose:

// πŸ‘ Good  
import UserService from './services/UserService'; // Service  
import { formatDate } from './utils/date';       // Utility  

// πŸ‘Ž Bad  
import Service from './Service';    // Too generic  
import foo from './helpers/foo';    // Unclear  
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 8. Configuration Files (env, config)

// πŸ‘ Good (clear prefixes)  
const DB_HOST = 'localhost';  
const MAX_UPLOAD_SIZE_MB = 10;  

// πŸ‘Ž Bad  
const host = 'localhost'; // No context  
const maxSize = 10;       // Units unclear  
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 9. Types (TypeScript)

  • Interfaces: PascalCase + I (if project convention).

  • Union types: Descriptive names.

// πŸ‘ Good  
interface IUser { ... }  
type PaymentStatus = 'pending' | 'completed';  

// πŸ‘Ž Bad  
interface user { ... }  
type status = 'pending' | 'completed';  
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 10. Async Operations (Prefixes: fetch, load, sync)

// πŸ‘ Good  
async function fetchPosts() { ... }  
const isLoading = false;  

// πŸ‘Ž Bad  
async function getData() { ... }  // Unclear if HTTP request  
const loading = false;            // Could be component state  
Enter fullscreen mode Exit fullscreen mode

Key Takeaways: Where Else Is Naming Important?

  • State management (Redux, Pinia): userSlice, useCartStore.

  • Error classes: ValidationError, NetworkError.

  • Project files: user.controller.js, date.utils.js.

  • Git commits: feat: add user login, fix: button click handler.

πŸ’° Golden Rule:
A name should reflect what it is and where it’s used.


Read more:

"JavaScript Variable Naming: Rules You Can’t Ignore" (second part)
"How to Name Functions in JavaScript: A Practical Guide" (third part)

Top comments (0)