Содержание Глава 1. Что такое TypeScript на самом деле →

Введение

Введение

Почему остальные книги учат не тому

Откройте почти любой курс, статью или книгу про TypeScript, и в первых же абзацах вам скажут одно и то же: это JavaScript, к которому приделали аннотации типов, чтобы ловить опечатки и забытые поля. Дальше идут таблицы — вот так пишется string, вот так number, вот так помечается необязательное свойство, — и обещание, что теперь редактор будет подсказывать, а глупые ошибки отвалятся ещё до запуска. Всё это правда. И всё это объясняет, почему опытный программист со статически типизированным прошлым смотрит на TypeScript свысока.

Поставьте себя на его место. Человек писал на Java или C# пятнадцать лет. Он знает, что такое система типов: она проверяет программу насквозь, она реальна в рантайме, на неё можно опереться. Ему показывают язык, где типы — это, по сути, аккуратный линтер: подсказки в редакторе, ловушка для опечаток, страховка от undefined is not a function. Полезно — но несерьёзно. Игрушка поверх динамического языка, который он и так считал несерьёзным. Он закрывает вкладку и возвращается к своему компилятору, который не врёт.

Проблема не в том, что он ошибается в фактах. Аннотации действительно ловят опечатки, редактор действительно подсказывает. Проблема в том, что ему показали инструмент и выдали его за язык. Он увидел обвязку и решил, что внутри ничего нет. А внутри — целая парадигма, со своей логикой, своими разменами и своей эстетикой, которую не видно, пока смотришь на TypeScript как на «JavaScript с подсказками». Эта книга исходит из обратной посылки и адресована в первую очередь тому самому скептику: не для того, чтобы переубедить его похвалами, а чтобы показать ему то, что от него спрятали.

Парадигма, а не аннотации

Тезис книги простой и неудобный: TypeScript — самостоятельная парадигма, а не косметика над JavaScript. У неё есть внутренняя логика, из которой выводится почти каждое решение, включая те, что снаружи выглядят странными или непоследовательными. У неё есть собственный способ думать о данных — не «к какому классу принадлежит объект», а «какую форму имеет значение». И у неё есть набор осознанных компромиссов, которые стоит разбирать с тем же интересом, с каким разбирают философию C++ или Lisp, — не потому, что они идеальны, а потому, что за каждым стоит понятный выбор и понятная цена.

Отсюда — что эта книга делает и чего не делает. Она не учит синтаксису. Синтаксис прилагается даром: его можно подсмотреть в документации за десять минут, и ни один справочник конструкций тут не нужен. Она занята другим — перепрошивкой интуиций. Цель — чтобы вы перестали думать таксономией классов и начали думать формами значений; перестали видеть в системе типов декоративную обвязку и увидели в ней программируемый язык; перестали воспринимать каждую «дыру» как недосмотр и поняли, из какого единственного ограничения она вытекает.

Это значит, что книга объясняет почему, а не как. Каждая конструкция вводится через проблему, которую она решает, и через размен, на который пошли её авторы. Не «вот десять способов объявить тип», а «вот одно свойство языка, и вот как из него растёт всё остальное». Если вам нужен список рецептов — это не та книга. Если вам интересно, почему рецепты именно такие, — та.

Кому и при каком условии

Книга написана для опытных программистов, и особенно — для пришедших из номинативно-типизированного ООП: Java, C#, Kotlin. Не для новичков. Тут нет «с чего начать программировать» и нет бережного въезда в основы; предполагается, что вы уже умеете писать код, читать чужой и спорить о дизайне. Задача книги — не дать вам первый язык, а сломать и пересобрать интуиции, которые в других языках служили вам верой и правдой, а в TypeScript молча работают против вас.

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

Знание Java предполагается, но не обязательно. Java в книге — не эталон и не объект нападок, а зеркало: знакомое, в котором отчётливее видно незнакомое. Если вы не писали на Java, вы ничего не потеряете — основной текст нигде не опирается на это знание и самодостаточен без него.

Как читать: блоки «Глазами джависта» и ритм главы

Сравнения с Java вынесены в отдельные, визуально отбитые блоки «Глазами джависта». Они делают двойную работу. Для читателя с Java-фоном это система координат: новое объясняется через знакомое, и перенос интуиции проверяется на прочность — где она держится, а где предаёт. Эти блоки не переводят с одного языка на другой; они вскрывают перенесённые допущения. То, что джавист считал силой Java, нередко оказывается её консервативным компромиссом; то, что он принял за легкомыслие TypeScript, — продуманным разменом. Если же Java вам незнакома, блоки можно пропускать целиком, не теряя нити: всё необходимое сказано в основном тексте.

У глав есть постоянный ритм, и его стоит знать заранее, чтобы ориентироваться. Каждая типовая глава идёт шестью тактами: открывается живой проблемой или ложной интуицией, чаще всего принесённой из другого языка; строит концепцию от первого принципа наращиваемыми примерами, где каждый отвечает на вопрос предыдущего; даёт блок «Глазами джависта»; честно разбирает острые края — места, где конструкция ломается; формулирует парадигмальный сдвиг под заголовком «Как думать»; и завершается коротким итогом. Введение и Заключение этому шаблону не подчиняются — это открывающее и закрывающее эссе.

Острые края — отдельный принцип, а не оговорка. Книга показывает дыры намеренно. Несостоятельность системы типов, места, где компилятор соглашается на ложь, границы, за которыми гарантия испаряется, — всё это разбирается прямо, как часть аргумента, а не как мелкий шрифт в конце. Язык, который скрывает свои компромиссы, нельзя понять; язык, который их объясняет, — можно. TypeScript второй.

Один факт, который нужно унести с собой

Если из всего Введения вы запомните одну вещь, пусть это будет вот эта. В одном .ts-файле живут две программы — проверяющая (type checker, рассуждает о типах во время компиляции) и исполняющая (движок JavaScript, работает с голым кодом в рантайме), — связанные стиранием (type erasure, удалением типов перед запуском). Проверяющий разбирается с аннотациями и уходит. Исполняющий получает код, из которого все типы физически вырезаны, и гоняет его, ничего о них не зная. Эти двое не встречаются: к моменту запуска от типов не остаётся ни байта.

Из этого следствие, неожиданное для тех, кто привык к тяжёлым компиляторам: инструмент — часть языка, а не настройка сбоку. Компилятор tsc и его флаги — это не сервис, который можно подкрутить по вкусу; они определяют, какой именно язык вы видите. Поэтому через всю книгу strict (семейство флагов строгой проверки) включён по умолчанию. С ним и без него TypeScript — буквально разные языки с разными гарантиями, и обсуждать имеет смысл только строгий: нестрогий — это совсем другая, гораздо более снисходительная система, в которой половина аргументов книги теряет силу.

Не воспринимайте этот факт как готовую модель — это затравка, а не установка. Полную картину строит глава 1; здесь — обещание. Обещание такое: почти всё, что в TypeScript кажется странным, нелогичным или непоследовательным, — это один и тот же факт в разных костюмах. Почему типов нет в рантайме, почему instanceof работает, а с типом из type — нет, почему catch не типизируется, почему на границах нужна валидация, зачем нужны type guard’ы и Zod, — всё это не список исключений, который надо зубрить, а следствия одного ограничения. Глава 1 делает его конкретным; остальная книга разворачивает.

А разворачивается она шестью частями, и вот их карта. Часть I ставит модель: два языка в одном файле, структурная типизация, стирание, вывод типов, компилятор как проверяющая программа. Часть II — алгебра значений: переход от «типы классифицируют» к «типы складываются», union’ы и пересечения, сужение, размеченные объединения, честный null. Часть III пересобирает объектный фасад — объекты, функции, интерфейсы, классы — на структурный лад. Часть IV, сердце книги, показывает систему типов как полноценный язык программирования: дженерики как функции над типами, условные и сопоставленные типы, рекурсию и её пределы. Часть V спускается на границу рантайма, где гарантии испаряются и начинается ваша личная ответственность. Часть VI — синтез: как проектировать и что считать хорошим вкусом, когда всё предыдущее стало интуицией.

Как эта книга попытается вас влюбить

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

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

И острые края — снова, потому что это про доверие между книгой и читателем. Дыры показываются, а не прячутся. С вами говорят как с равным, которому можно сообщить неприятную правду про инструмент, которым он пользуется. Это не справочник, по которому ищут забытый синтаксис. Это попытка передать способ видеть.

Что изменится к концу

К последней странице, если книга сработает, вы перестанете писать на TypeScript как на «Java с другим синтаксисом» и начнёте писать на TypeScript. Это не фигура речи, а вполне конкретная смена привычек. Вы будете мыслить формами значений, а не иерархиями классов; выводом типов, а не сплошными объявлениями; алгебраически — объединениями и пересечениями вместо наследования. Вы научитесь проектировать API так, чтобы недопустимое состояние просто не компилировалось. Вы будете точно знать, где компилятор перестаёт гарантировать что-либо, и ставить настоящую проверку именно там, на границе, а не полагаться на аннотацию, которой в рантайме давно нет.

И — то, ради чего всё это, — вы начнёте получать от системы типов удовольствие, которого статически типизированный мейнстрим вам, скорее всего, никогда не давал. Каким именно окажется это удовольствие, договорит Заключение; забегать вперёд не будем. Пока достаточно начать с одного файла, в котором, как выясняется, живут две программы.

Содержание Глава 1. Что такое TypeScript на самом деле →