Clean Code in TypeScript: Rules, Examples, and Life Hacks

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why Clean Code in TypeScript is Not a Luxury, but a Necessity

Every developer has at least once encountered a situation: you open a project written a couple of months ago and don't understand what's going on. Variables are named a, b, data, functions are 200 lines long, and types are used sporadically. Sound familiar?

TypeScript gives us a powerful tool — static typing. But by itself, it doesn't make code clean. You can write terrible code in TypeScript, just as in any other language. Clean code is a discipline, a style, and a sign of respect for yourself and your colleagues.

In this article, we'll break down how to write clean code in TypeScript that is easy to read, maintain, and scale. You'll learn about SOLID principles, strong typing, naming conventions, working with interfaces, and much more. Let's go!



1. Naming — The Face of Your Code

Proper naming of variables, functions, and classes is 50% of success. A good name should answer the questions: "What is this?" or "What does this function do?".



Variables and Constants

Use nouns and camelCase. Avoid single-letter names (except in loops).

// Badconst d = new Date();const u = users.find(u => u.id === 5);

// Goodconst currentDate = new Date();const activeUser = users.find(user => user.id === 5);


Functions

Function names should start with a verb. This immediately makes it clear what action is being performed.

// Badfunction data(id: number) { ... }

// Goodfunction fetchUserData(id: number): Promise<UserData> { ... }


Classes and Interfaces

Classes are nouns in PascalCase. Interfaces are also, but often with the I prefix (though there is debate in the community). It's better to just give a clear name without a prefix.

// Badinterface IUser {  name: string;}

// Goodinterface User { name: string; email: string;}


2. Strong Typing — Your Best Friend

TypeScript was created so that types work for you. Do not use any unless absolutely necessary. Every time you write any, you disable the compiler's protection.



Avoid any

// Badfunction process(data: any) {  return data.name;}

// Goodinterface Item { name: string; price: number;}

function process(data: Item): string { return data.name;}


Use Union and Intersection Types

When a variable can accept multiple types, use Union (|). For combinations, use Intersection (&).

type Status = 'active' | 'inactive' | 'pending';type AdminUser = User & { role: 'admin' };


Generics — Universal Functions

Generics allow you to write flexible code without losing type safety.

function firstElement<T>(arr: T[]): T | undefined {  return arr[0];}

const num = firstElement([1, 2, 3]); // numberconst str = firstElement(['a', 'b']); // string


3. SOLID — Principles for Professionals

The SOLID principles help build flexible and maintainable architecture. Let's look at each one using TypeScript examples.



Single Responsibility (SRP)

A class or function should have only one reason to change.

// Bad: the class does everythingclass UserService {  createUser() { ... }  sendEmail() { ... }  generateReport() { ... }}

// Good: separate responsibilitiesclass UserCreator { ... }class EmailService { ... }class ReportGenerator { ... }


Open/Closed (OCP)

Classes are open for extension but closed for modification. Use interfaces and inheritance.



Liskov Substitution (LSP)

Subclasses should be able to replace the base class without changing the program's behavior.



Interface Seg

Blogs

Book Recommendations