DEV Community

Adarsh Hasnah
Adarsh Hasnah

Posted on

Kebab-Case Filenames and PascalCase Classes: Naming Conventions That Scale

Naming conventions are not cosmetic.
They are how developers understand intent at scale.

In modern JavaScript and TypeScript projects, inconsistent naming leads
to:

  • slower onboarding
  • harder navigation
  • unnecessary debates in code reviews

After years of working with Node.js, TypeScript, and modular systems,
one combination consistently delivers clarity with minimal friction:

  • kebab-case for filenames
  • Explicit responsibility-based suffixes
  • PascalCase for classes and public APIs

This article explains why these naming conventions work, and why
they scale better than common alternatives.


Why Naming Conventions Matter in TypeScript Projects

File and symbol names are human interfaces.

Good naming conventions should be:

  • Predictable
  • Easy to scan
  • Cross-platform safe
  • Tooling-friendly
  • Explicit about responsibility

The goal is not cleverness --- it's removing cognitive load.


Why Use kebab-case for Filenames?

Example (Suffix-Enforced)

user.service.ts
email-notification.controller.ts
cache-entry.repository.ts
data-cleanup.job.ts
Enter fullscreen mode Exit fullscreen mode

Pattern:

<domain-or-feature>.<responsibility>.ts
Enter fullscreen mode Exit fullscreen mode

1. Cross-Platform Safety

Operating systems treat filenames differently:

  • Windows / macOS → case-insensitive
  • Linux → case-sensitive

These two files are a common source of bugs:

UserService.ts
userService.ts
Enter fullscreen mode Exit fullscreen mode

Using kebab-case eliminates ambiguity and avoids OS-specific issues.


2. Native to Web and Tooling Ecosystems

kebab-case is already the default for:

  • URLs
  • npm packages
  • Docker images
  • GitHub repositories
  • CI/CD pipelines

Using it for filenames creates consistency across your entire
toolchain
.


3. Better Readability for Long Filenames

Long filenames are unavoidable in real-world systems.

emailNotificationRetryConfigurationService.ts
Enter fullscreen mode Exit fullscreen mode

vs

email-notification-retry-configuration.service.ts
Enter fullscreen mode Exit fullscreen mode

kebab-case improves scannability and reduces visual parsing effort.


Responsibility-Based Suffixes Improve Clarity

While kebab-case improves readability, suffixes communicate
intent
.

Common Responsibility Suffixes

.entity.ts
.value-object.ts
.repository.ts
.service.ts
.use-case.ts
.controller.ts
.route.ts
.dto.ts
.mapper.ts
.job.ts
.event.ts
.policy.ts
Enter fullscreen mode Exit fullscreen mode

Why the Responsibility Suffix Comes Last

Responsibility is always the final signal:

*.service.ts
*.repository.ts
*.controller.ts
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Faster scanning
  • Easier filtering
  • Tooling enforcement (linting, boundaries)
  • Clear architectural intent

You should understand what a file is without opening it.


Avoid Embedding Responsibility in Names

❌ Avoid:

user-service.ts
email-notification-controller.ts
Enter fullscreen mode Exit fullscreen mode

✅ Prefer:

user.service.ts
email-notification.controller.ts
Enter fullscreen mode Exit fullscreen mode

This keeps responsibility explicit, standardized, and enforceable.


Why Use PascalCase for Classes?

Example

class UserService {}
class EmailNotificationSender {}
class DataCleanupJob {}
Enter fullscreen mode Exit fullscreen mode

1. Immediate Type Signaling

PascalCase instantly signals:

This is a class, type, or conceptual construct.

This distinction matters when scanning large codebases.


2. Aligns With TypeScript Standards

In TypeScript: - Classes → PascalCase - Interfaces → PascalCase -
Types → PascalCase

interface MessageSender {}
class SmtpMessageSender implements MessageSender {}
Enter fullscreen mode Exit fullscreen mode

Consistency reduces mental overhead and ambiguity.


3. File-to-Class Naming Symmetry

user.service.ts            → class UserService
email-notification.job.ts  → class EmailNotificationJob
cache-entry.entity.ts      → class CacheEntry
Enter fullscreen mode Exit fullscreen mode

This symmetry makes navigation predictable and intuitive.


Naming Functions: PascalCase vs camelCase

Practical Rule

  • Public / exported / use-case functionsPascalCase
  • Local helper functionscamelCase
export function RegisterUser() {}
export function SendNotification() {}

function sanitizeInput() {}
function retryWithBackoff() {}
Enter fullscreen mode Exit fullscreen mode

PascalCase functions read like actions, not utilities.


Why Not camelCase or snake_case for Filenames?

snake_case

  • Rare in modern JS/TS ecosystems
  • Uncommon in URLs and tooling
  • Inconsistent with npm and Docker norms

camelCase

  • Harder to scan
  • Case-sensitivity issues
  • Visually dense in file explorers

For filenames, kebab-case is the most readable and compatible option.


Reduced Cognitive Load Is the Real Benefit

Once these conventions are established: - naming debates disappear -
navigation becomes intuitive - onboarding gets faster

Good conventions fade into the background --- exactly where they belong.


TL;DR: Recommended Naming Conventions

Filenames

kebab-case + explicit responsibility suffix
Enter fullscreen mode Exit fullscreen mode

Classes / Types

PascalCase
Enter fullscreen mode Exit fullscreen mode

Local variables & helpers

camelCase
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

Clean naming conventions are not about style.\
They're about clarity, scalability, and developer experience.

When filenames communicate responsibility and symbols reflect intent,
your codebase becomes easier to reason about --- today and years from
now.

Consistency beats cleverness. Every time.

Top comments (0)