Ревью кода на TypeScript: 10 ошибок, которые бесят senior-ов

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

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

Начать курс

Введение: Почему ваше ревью кода на TypeScript выглядит как красная лампочка на пульте?

Вы когда-нибудь отправляли pull request, а через час получали 20 комментариев от senior-разработчика, половина из которых начиналась со слов «это можно сделать лучше»? Знакомо. Если вы пишете на TypeScript, но ваш код всё ещё вызывает у коллег желание переписать его с нуля — эта статья для вас.

Мы в PythonLib часто сталкиваемся с ситуациями, когда разработчики, даже зная синтаксис TypeScript, допускают одни и те же ошибки. Эти ошибки не ломают код, но делают его нечитаемым, небезопасным и трудносопровождаемым. Сегодня я покажу вам 10 типичных замечаний, которые senior-ы пишут на code review TypeScript, и как их избежать. Готовьтесь к рефакторингу!

1. «Any» — твой враг, а не друг

Самая частая претензия на любом ревью кода на TypeScript — это использование any. Кажется, что проще написать const data: any = await fetch(...), чем разбираться с типами. Но senior-ы видят это как красную тряпку.

Плохо:

function processUser(user: any) {
  console.log(user.name.toUpperCase());
}

Хорошо:

interface User {
  id: number;
  name: string;
  email: string;
}

function processUser(user: User): void {
  console.log(user.name.toUpperCase());
}

Почему это важно? TypeScript теряет весь смысл, если вы используете any. Вы буквально отключаете систему типов. Если данные приходят из API — создайте интерфейс. Если тип сложный — используйте unknown с проверками. Это одно из главных правил TypeScript best practices.

2. Игнорирование strict mode

Многие проекты отключают строгий режим в tsconfig.json, потому что «так быстрее» или «типы бесят». Senior-разработчик на TypeScript сразу заметит, что ваш код не проверяет null и undefined.

Плохо (strict: false):

function getLength(str: string) {
  return str.length; // str может быть null, и это упадёт
}

Хорошо (strict: true):

function getLength(str: string | null): number {
  if (str === null) return 0;
  return str.length;
}

Совет: Включайте strict: true в tsconfig.json. Это заставит вас писать более безопасный код. На ревью кода TypeScript это будет плюсом, а не минусом.

3. Магия с типами: избыточная сложность

Иногда разработчики пытаются показать, как они круты, и пишут такие типы, что даже senior-ы чешут голову. Например, условные типы с вложенными дженериками там, где можно обойтись простым интерфейсом.

Плохо (over-engineering):

type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};

Хорошо (простота):

interface Config {
  readonly apiUrl: string;
  readonly timeout: number;
}

Senior-ы ценят читаемость кода. Если ваш тип можно заменить на интерфейс с тремя полями — сделайте это. Не усложняйте без необходимости.

4. Неправильная обработка ошибок

Типичная ошибка на code review TypeScript — это try-catch с any или пустой блок catch. Senior-ы сразу укажут на это.

Плохо:

try {
  const data = await fetchData();
} catch (e) {
  console.log('Ошибка');
}

Хорошо:

try {
  const data = await fetchData();
} catch (error: unknown) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error('Неизвестная ошибка', error);
  }
}

Используйте unknown для ошибок. Это заставляет вас проверять тип перед использованием. Senior-ы любят такой подход.

5. Отсутствие типов для функций высшего порядка

Когда вы передаёте колбэки или используете map/filter, часто забывают типизировать параметры. Это приводит к неявному any.

Плохо:

const names = users.map(u => u.name);

Хорошо:

const names: string[] = users.map((user: User) => user.name);

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

6. Использование enum вместо union types

Enum-ы в TypeScript — это спорная тема. Senior-ы часто рекомендуют использовать union types вместо числовых enum, потому что они проще и безопаснее.

Плохо (enum):

enum Status {
  Active,
  Inactive,
  Pending
}

Хорошо (union):

type Status = 'active' | 'inactive' | 'pending';

Union types легче рефакторить, они не создают лишнего кода при компиляции, и их проще проверять. Это один из советов по TypeScript, который сэкономит вам часы дебага.

7. Неправильная работа с async/await

Многие забывают, что async-функция всегда возвращает Promise. Senior-ы на ревью кода на TypeScript обращают внимание на то, как вы обрабатываете асинхронные вызовы.

Плохо:

async function getData() {
  return fetch('/api');
}
// Тип возврата: Promise<Response>

Хорошо:

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

Всегда указывайте возвращаемый тип для async-функций. Это делает код предсказуемым.

8. Избыточное использование type guards

Защитники типов — это круто, но некоторые разработчики пишут их там, где можно обойтись простым сужением.

Плохо:

function isString(value: unknown): value is string {
  return typeof value === 'string';
}

if (isString(input)) { ... }

Хорошо:

if (typeof input === 'string') { ... }

Используйте type guards только тогда, когда логика слож

Блоги

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