Clean Code на TypeScript: принципы и примеры на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Clean Code на TypeScript: принципы и примеры на практике

Каждый разработчик сталкивался с ситуацией, когда через месяц после написания кода его собственный скрипт кажется чужим и непонятным. В мире TypeScript, где строгая типизация даёт преимущество, принципы Clean Code становятся особенно важными. Чистый код — это не просто эстетика, а инструмент для уменьшения багов, ускорения разработки и облегчения командной работы. В этой статье мы разберём ключевые принципы Clean Code на TypeScript с реальными примерами, которые помогут вам писать код, который легко читать, тестировать и поддерживать.

1. Именование: говорите, что делает переменная

Первое, что видит разработчик — это имена переменных, функций и классов. Плохое имя заставляет читателя тратить время на расшифровку. В TypeScript с его системой типов имя должно быть самодокументируемым.

Плохой пример:

const d = new Date();
const arr = [1, 2, 3];
function proc(x: number, y: number) {
    return x * y;
}

Хороший пример:

const currentDate = new Date();
const userScores: number[] = [1, 2, 3];
function calculateArea(width: number, height: number): number {
    return width * height;
}

Используйте существительные для переменных и глаголы для функций. Избегайте сокращений (кроме общепринятых, таких как id или url). TypeScript позволяет добавить типы, но имя всё равно должно отражать суть.

2. Функции: маленькие, чистые и предсказуемые

Функция должна делать только одну вещь. Если вы не можете придумать короткое имя для функции — скорее всего, она делает слишком много. Также важно избегать побочных эффектов.

Принцип единой ответственности (SRP) на уровне функций:

// Плохо: функция делает всё сразу
function processUserData(user: User): void {
    // Валидация
    if (!user.email) throw new Error('Email required');
    // Сохранение в БД
    database.save(user);
    // Отправка email
    emailService.sendWelcome(user.email);
}

// Хорошо: разделяем ответственность
function validateUser(user: User): boolean {
    return user.email !== undefined;
}

function saveUser(user: User): void {
    database.save(user);
}

function sendWelcomeEmail(email: string): void {
    emailService.send(email);
}

function processUser(user: User): void {
    if (!validateUser(user)) {
        throw new Error('Invalid user data');
    }
    saveUser(user);
    sendWelcomeEmail(user.email);
}

Также избегайте большого количества параметров. Если их больше двух — объедините в объект:

// Плохо
function createUser(name: string, email: string, age: number, isAdmin: boolean): void {}

// Хорошо
interface CreateUserParams {
    name: string;
    email: string;
    age: number;
    isAdmin: boolean;
}

function createUser(params: CreateUserParams): void {}

3. Типизация: используйте возможности TypeScript на полную

Одно из главных преимуществ TypeScript — строгая типизация. Но многие разработчики используют any как костыль, убивая всю пользу. Чистый код на TypeScript — это код, где типы явно описаны, а не угадываются.

Избегайте any:

// Плохо
function getData(): any {
    return fetch('/api/data');
}

// Хорошо
interface ApiResponse {
    id: number;
    title: string;
}

async function getData(): Promise<ApiResponse> {
    const response = await fetch('/api/data');
    return response.json();
}

Используйте discriminated unions для сложных состояний:

// Плохо: неясно, что в объекте
type Status = 'loading' | 'success' | 'error';

interface State {
    status: Status;
    data?: Data;
    error?: string;
}

// Хорошо: каждый статус — отдельный интерфейс
interface LoadingState { status: 'loading'; }
interface SuccessState { status: 'success'; data: Data; }
interface ErrorState { status: 'error'; error: string; }

type State = LoadingState | SuccessState | ErrorState;

function handleState(state: State) {
    switch (state.status) {
        case 'loading':
            console.log('Загрузка...');
            break;
        case 'success':
            console.log('Данные:', state.data);
            break;
        case 'error':
            console.error('Ошибка:', state.error);
            break;
    }
}

Такой подход делает код безопасным и самодокументируемым — вы точно знаете, какие поля доступны в каждом состоянии.

4. Комментарии и документация: меньше — лучше

Одно из правил Clean Code гласит: «Хороший код сам себя документирует». Комментарии не должны объяснять что делает код (это должно быть ясно из названий и структуры), а почему он делает это именно так.

Плохо:

// Увеличиваем счётчик на 1
counter += 1;

// Проверяем, что пользователь авторизован
if (user.isLoggedIn) { ... }

Хорошо:

// Комментарий объясняет бизнес-логику, а не код
// Используем Math.floor, потому что API округляет в меньшую сторону
const finalPrice = Math.floor(price * discount);

// TODO: Удалить после миграции на новую версию API (v2)
function legacyAuth() { ... }

Для публичных API используйте JSDoc, но не злоупотребляйте:

/**
 * Рассчитывает стоимость заказа с учётом скидки.
 * @param basePrice - базовая цена
 * @param discount - процент скидки (0-100)
 * @returns Итоговая стоимость
 */
function calculateDiscountedPrice(basePrice: number, discount: number): number {
    return basePrice * (1 - discount / 100);
}

Заключение

Clean Code на TypeScript — это не набор жёстких правил, а философия, которая делает вашу жизнь проще. Начните с малого: давайте переменным осмысленные имена, разбивайте большие функции на маленькие, используйте строгую типизацию и не пишите комментарии там, где код говорит сам за себя.

Помните: вы пишете код не для компьютера, а для людей — включая себя через полгода. Применяя эти принципы на практике, вы заметите, как уменьшается количество багов, а рефакторинг перестаёт быть страшным. Начните прямо сегодня — возьмите один из своих проектов и попробуйте применить хотя бы один принцип из этой статьи.

Если вы хотите углубиться в тему, рекомендую книгу Роберта Мартина

Блоги

Рекомендаций по книгам