Типичный день TypeScript разработчика: код, баги и ревью

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

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

Начать курс

Доброе утро, TypeScript: как начинается день разработчика

Представьте: 9:00 утра. Вы открываете ноутбук, завариваете кофе и видите в Telegram сообщение от коллеги: «Слушай, я вчера написал функцию, но TypeScript ругается на тип unknown. Помоги!». Знакомо? Добро пожаловать в типичный рабочий день TypeScript разработчика. Это не просто написание кода — это искусство балансировать между строгой типизацией, дедлайнами и бесконечными рефакторингами.

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

Утро: стендап и код-ревью

9:30 — Daily standup

Короткая встреча с командой. Вы говорите: «Вчера закончил модуль авторизации, сегодня планирую разобраться с типизацией ответов от API». И тут же слышите: «А не хочешь вынести интерфейсы в отдельный файл? У нас же code style». TypeScript разработчик всегда думает на шаг вперёд: интерфейсы, дженерики, utility types.

Пример: вы обсуждаете типизацию ответа от сервера. Вместо того чтобы писать any, вы предлагаете:

interface ApiResponse<T> {
  data: T;
  error: string | null;
  status: number;
}

type User = {
  id: string;
  name: string;
  email: string;
};

// Использование
const response: ApiResponse<User[]> = await fetchUsers();

Коллеги кивают — это правильный подход. TypeScript разработчик знает: хорошая типизация — половина успеха.

10:00 — Код-ревью: находим баги до того, как они найдут нас

После стендапа вы открываете Pull Request от джуниора. Он написал функцию для валидации email. Код работает, но TypeScript подсказывает: Type 'string | undefined' is not assignable to type 'string'. Вы оставляете комментарий:

// ❌ Проблема: не обработаны null/undefined
function validateEmail(input: string | null | undefined): boolean {
  if (!input) return false;
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(input);
}

// ✅ Решение: используем guards и optional chaining
function validateEmail(input: unknown): input is string {
  return typeof input === 'string' && 
         input.length > 0 && 
         /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input);
}

Вы объясняете: TypeScript разработчик всегда думает о краевых случаях. Типизация — это не про ограничения, а про безопасность.

Середина дня: написание кода и работа с дженериками

11:30 — Главная задача дня: рефакторинг легаси

Вы берётесь за старый JavaScript-модуль, который нужно переписать на TypeScript. Там есть функция, которая принимает «что угодно» и возвращает «что угодно». Классика:

// 🚫 Старый JS-код
function processData(data) {
  if (data.type === 'user') {
    return { id: data.id, name: data.name };
  }
  if (data.type === 'order') {
    return { orderId: data.id, total: data.total };
  }
  return null;
}

Вы превращаете это в строго типизированный код с помощью discriminated unions:

// ✅ TypeScript-версия
type UserData = { type: 'user'; id: string; name: string };
type OrderData = { type: 'order'; id: string; total: number };
type InputData = UserData | OrderData;

type ProcessedResult<T> = T extends UserData 
  ? { id: string; name: string }
  : T extends OrderData 
  ? { orderId: string; total: number }
  : never;

function processData<T extends InputData>(data: T): ProcessedResult<T> {
  if (data.type === 'user') {
    return { id: data.id, name: data.name } as ProcessedResult<T>;
  }
  return { orderId: data.id, total: data.total } as ProcessedResult<T>;
}

Теперь TypeScript сам выводит правильный тип результата в зависимости от входных данных. Коллега заглядывает через плечо и говорит: «Круто, я бы так не смог». Вы улыбаетесь — это обычный рабочий день TypeScript разработчика.

13:00 — Обед и мысли о типизации

За обедом вы листаете Telegram-каналы по TypeScript. Видите пост про satisfies operator и думаете: «Надо будет применить в проекте». Даже в перерыве вы остаётесь в контексте — TypeScript разработчик живёт в мире типов.

После обеда: дебаггинг и работа с API

14:00 — Интеграция с внешним API

Вы подключаете новый сервис. Документация говорит: «Ответ может быть таким или таким, а иногда пустым». Без TypeScript это был бы хаос. Вы создаёте точную модель данных:

// Типизация нестабильного API
type ExternalApiResponse = 
  | { status: 'success'; data: Record<string, unknown> }
  | { status: 'error'; message: string }
  | { status: 'pending'; estimatedTime: number };

async function fetchExternalData(): Promise<ExternalApiResponse> {
  const response = await fetch('https://api.example.com/data');
  const raw: unknown = await response.json();
  
  // Проверка структуры
  if (typeof raw === 'object' && raw !== null && 'status' in raw) {
    return raw as ExternalApiResponse;
  }
  throw new Error('Invalid API response format');
}

Вы используете unknown вместо any — это принципиально. TypeScript разработчик никогда не теряет контроль над данными.

15:30 — Баг-хантинг: таинственный undefined

Приходит баг-репорт: «Кнопка не работает, если пользователь не заполнил поле». Вы открываете код и видите:

function handleSubmit(data: { name?: string }) {
  const userName = data.name.toUpperCase(); // 💥 Ошибка!
}

Вы исправляете за 30 секунд:

function handleSubmit(data: { name?: string }) {
  const userName = data.name?.toUpperCase() ?? 'Гость';
}

Optional chaining и nullish coalescing — ваши лучшие друзья. Вы добавляете в код правило eslint: @typescript-eslint/no-unnecessary-condition. Теперь такая ошибка не пройдёт код-ревью.

Вечер: подготовка к завтрашнему дню

17:00 — Пишем тесты и документацию

Вы садитесь писать unit-тесты. TypeScript помогает и здесь: тесты становятся самодокументируемыми.

import { describe, it, expect } from 'vitest';

describe('processData', () => {
  it('should process user data correctly', () => {
    const input: UserData = { type: 'user', id: '123', name: 'Alice' };                

Блоги

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