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 — везде, с первого дня, включая одноразовые скрипты. Если скрипт переживает первую неделю, я рад, что типы уже на месте. Если нет — лишняя минута на настройку ничего не стоила.