Skip to content
maksim zaytsev
Заметки

10 января 2024 · 6 мин

TypeScript, который масштабируется вниз

Частый аргумент против строгого TypeScript в маленьких проектах — что церемония того не стоит: это же «просто скрипт» или «просто прототип», зачем платить налог. Я перестал с этим соглашаться. Строгость одинаково хорошо работает и на маленьком масштабе, и на большом — просто решает разные задачи.

В большой кодовой базе строгие типы не дают одной команде сломать предположения другой. В скрипте на три файла они делают вещь поменьше, но не менее ценную: не дают сломать твои же собственные предположения через шесть недель, когда ты уже забыл, почему поле может быть null.

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

function parseRow(row: string[]): { email: string; amount: number } {
  return {
    email: row[0],
    amount: Number(row[1]),
  };
}

С выключенным strict это компилируется. С включённым noUncheckedIndexedAccess row[0] становится string | undefined, и компилятор задаёт вопрос, который я должен был задать себе сам: что происходит на короткой строке? Честный ответ был такой: приложение падает на два вызова позже, со стектрейсом, который никуда не указывает. Починить это в источнике — проверить длину строки, вернуть что-то в духе Result — заняло десять минут и перенесло сбой туда, где его можно объяснить.

Проекты, где я пропускаю строгий режим, — это как раз те, к которым потом возвращаюсь с сожалением. Не потому что логика была сложной, а потому что код не говорил мне, что я имею право предполагать. Быстрый скрипт со слабыми типами пишется быстро, а вот доверять ему потом — долго, и этим человеком часто оказываюсь я сам.

Мой стандарт сейчас: strict: true, noUncheckedIndexedAccess: true — везде, с первого дня, включая одноразовые скрипты. Если скрипт переживает первую неделю, я рад, что типы уже на месте. Если нет — лишняя минута на настройку ничего не стоила.