Документация по TypeScript
Краткий справочник по TypeScript с примерами. Прочитай концепцию, посмотри код, а затем потренируйся в курсе Coddy.
Начать пошаговый курс по TypeScriptНачало работы
- Что такое TypeScriptЧто такое TypeScript? Это JavaScript со статическими типами. Вы указываете типы значений, компилятор проверяет их до запуска кода, а на выходе получается обычный JavaScript, который работает в любом браузере, в Node.js, Deno и Bun. Введение в TypeScript для начинающих.
- TypeScript vs JavaScriptTypeScript это JavaScript плюс статическая система типов, которая проверяется до запуска кода. Сравниваем их бок о бок: синтаксис, что находит проверка типов, этап сборки, скорость, сложность изучения и как перевести проект с JavaScript на TypeScript.
- Установка TypeScriptУстановите TypeScript через npm как dev-зависимость проекта, проверьте версию командой npx tsc --version, создайте tsconfig.json через tsc --init и скомпилируйте первый файл. Глобальная установка, pnpm, Yarn и Bun, а также частые ошибки.
- Запуск TypeScriptПять способов запустить файл .ts: скомпилировать через tsc и запустить JavaScript, запустить напрямую через node file.ts (удаление типов), использовать tsx или ts-node, либо Deno и Bun. Какие из них проверяют типы, какой синтаксис поддерживают и что выбрать.
- tsconfig.jsontsconfig.json помечает папку как проект TypeScript и задаёт параметры компилятора. Важные параметры (target, module, moduleResolution, strict, rootDir, outDir, include, lib, types, noEmit, skipLibCheck), рекомендуемая стартовая конфигурация, extends и что изменилось в TypeScript 7.
- TypeScript 7TypeScript 7 это компилятор TypeScript, переписанный на Go как нативная программа: примерно в десять раз быстрее, с той же командой tsc и тем же языком. Что изменилось для пользователей (новые значения по умолчанию, удалённые параметры, отсутствие JavaScript API), каким инструментам ещё нужен TypeScript 6 и как обновиться.
- КомментарииTypeScript использует комментарии JavaScript // и /* */, а также комментарии JSDoc /** */, которые редакторы показывают при наведении. Кроме того, он читает несколько особых комментариев: @ts-expect-error, @ts-ignore, @ts-nocheck, @ts-check и директивы /// <reference>.
- TypeScript vs PythonTypeScript и Python оба высокоуровневые языки со сборкой мусора, но TypeScript проверяет типы до запуска кода, а подсказки типов в Python необязательны и игнорируются во время выполнения. Сравнение типизации, среды выполнения, скорости, экосистем и областей применения с одной и той же программой на обоих языках.
Базовые типы
- Базовые типыВстроенные типы TypeScript: string, number, boolean, bigint, symbol, null и undefined, а также массивы и объекты в двух словах. Как писать аннотацию типа, почему нет целочисленного типа и почему пишут string, а не String.
- Вывод типовБольшинство типов TypeScript выводит сам из значений, которые вы пишете. Разберём, что выводится для переменных, let и const, объектов, массивов и возвращаемых значений, как колбэки получают типы из контекста и где аннотация всё же нужна.
- СтрокиРабота со строками в TypeScript: интерполяция через шаблонные литералы, многострочные строки, проверка вхождения подстроки, основные методы и типы, которые они возвращают, и строковые литеральные типы.
- Строка в числоПреобразование строки в число в TypeScript через Number(), parseInt(), parseFloat() или унарный +: как каждый способ обрабатывает "42px", "" и "1e3", как безопасно проверить NaN и как превратить число обратно в строку.
- МассивыКак типизировать массивы в TypeScript: T[] и Array<T>, массивы объектов, массивы с несколькими типами, readonly-массивы и что возвращают map, filter, reduce и find. Плюс ловушка с includes у литеральных массивов.
- КортежиКортеж в TypeScript это массив с фиксированным числом элементов, типы которых известны по позиции, например [string, number]. Синтаксис, именованные, опциональные и rest-элементы, readonly-кортежи и as const, возврат кортежа из функции и отличие кортежей от массивов.
- Объектные типыКак типизировать объекты в TypeScript: встроенные объектные типы, опциональные свойства с ?, readonly-свойства, вложенные объекты, методы, проверка лишних свойств и разница между object, {} и Object.
- Enum (перечисления)Enum в TypeScript это именованный набор констант, например enum Direction { Up, Down }. Числовые и строковые перечисления, JavaScript, в который компилируется enum, обратное отображение, перебор enum, const enum и когда лучше выбрать объединение строковых литералов или объект с as const.
Особые типы
- Литеральные типыЛитеральный тип это тип ровно с одним значением, например "GET" или 404. Строковые, числовые и логические литеральные типы, объединения литералов, почему let расширяет тип, а const нет, что делает as const и параметры типа const.
- any vs unknownИ any, и unknown принимают любое значение. any отключает проверку типов для этого значения, а unknown заставляет проверить значение перед использованием. Разница между ними, сужение unknown, noImplicitAny и откуда any пробирается в типизированный код.
- Тип nevernever это тип без значений. Это тип возврата функций, которые никогда не завершаются, тип, который остаётся, когда сужение исключило все варианты, и основа исчерпывающих проверок switch. Откуда он берётся и чем отличается от void.
- null и undefinedСо strictNullChecks null и undefined становятся отдельными типами, которые TypeScript заставляет обрабатывать. Как их проверять, опциональная цепочка (?.), двойной вопросительный знак (??) и ??=, и чем необязательное свойство отличается от | undefined.
- Утверждение non-null (!)Восклицательный знак после значения, например user!, это оператор утверждения non-null: он убирает null и undefined из типа без какой-либо проверки во время выполнения. Что делает x!, формы явного присваивания let x!: T и prop!: T, чем они опасны и какие есть безопасные альтернативы.
Интерфейсы и псевдонимы типов
- ИнтерфейсыИнтерфейс даёт имя структуре объекта: какие у него свойства и какие типы они хранят. Как объявить интерфейс, необязательные и readonly свойства, методы, сигнатуры индекса, наследование, реализация в классе, слияние объявлений, обобщённые интерфейсы и как задать значения по умолчанию.
- Псевдонимы типовПсевдоним типа даёт имя любому типу через ключевое слово type: структурам объектов, объединениям, кортежам, функциям, обобщённым и рекурсивным типам. Синтаксис, как выглядит каждая форма и почему псевдоним это лишь имя, а не новый отдельный тип.
- Interface vs Typeinterface и type оба описывают структуры объектов, и в большинстве случаев подходит любой. Настоящие различия: слияние объявлений, объединения и сопоставленные типы, extends и пересечения, неявные сигнатуры индекса, сообщения об ошибках и производительность компилятора, плюс понятное правило выбора.
- Ключевое слово extendsКлючевое слово extends строит один тип из другого. Как расширить интерфейс (один или несколько), расширить псевдоним типа через &, переопределить тип свойства, заменить свойства через Omit, и что значит extends в классах, ограничениях дженериков и условных типах.
- Типы объединенияТип объединения вроде string | number означает, что значение может быть одним из нескольких типов. Что можно делать с объединением (только то, что поддерживают все его члены), как его сузить, объединения литералов и объектных типов, и чем (A | B)[] отличается от A[] | B[].
- Типы пересеченияТип пересечения A & B описывает значение, которое одновременно является A и B, поэтому у него есть все члены обоих. Как объединять объектные типы через &, почему конфликтующие свойства становятся never, почему пересечение объединений оставляет только общие члены и когда вместо этого использовать extends.
- Размеченные объединенияРазмеченное объединение это объединение объектных типов с общим литеральным свойством-тегом, например kind или status. Проверка тега сужает весь объект. Сам приём, сужение через switch, исчерпывающие проверки через never и как моделировать результаты API, состояние запроса и конечные автоматы.
Функции
- ФункцииКак типизировать функции в TypeScript: аннотировать каждый параметр, указывать или выводить возвращаемый тип, использовать void для функций, которые ничего не возвращают, и типизировать стрелочные функции, функциональные выражения, async-функции и параметр this.
- Типы функцийКак записать тип функции в TypeScript: стрелочный синтаксис (a: number) => string, псевдонимы типов для функций, типизация стрелочных функций и колбэков, сигнатуры вызова и конструирования и почему тип Function слишком широкий.
- Опциональные параметрыКак сделать параметр в TypeScript опциональным через ?, задать ему значение по умолчанию или собрать любое число аргументов rest-параметром. Правила порядка, пропущенный аргумент и undefined, объекты опций и опциональные параметры в типах функций.
- Перегрузка функцийПерегрузки функций в TypeScript позволяют одной функции иметь несколько сигнатур вызова, каждую со своим возвращаемым типом. Схема из сигнатур перегрузки и реализации, правила, которые проверяет компилятор, когда лучше параметр-объединение и перегрузки в классах.
Сужение и проверка типов
- Сужение типовСужение это то, как TypeScript превращает широкий тип вроде string | number в конкретный внутри if, switch или после раннего return. Все формы сужения в одном месте: typeof, истинность, равенство, in, instanceof, присваивания, предикаты типов и размеченные объединения.
- Оператор typeofУ typeof в TypeScript две задачи. В коде это оператор JavaScript, который во время выполнения возвращает "string", "number", "object" и так далее, а TypeScript сужает по нему типы. В типе это запрос типа, который копирует тип переменной, как в keyof typeof obj и ReturnType<typeof fn>.
- Оператор instanceofinstanceof во время выполнения проверяет, создан ли объект определённым классом, а TypeScript сужает переменную до этого класса. Как он работает с вашими классами и подклассами Error, почему не может проверить интерфейс или псевдоним типа и где даёт неожиданные ответы.
- Защитники типовЗащитник типа (type guard) это проверка во время выполнения, которую понимает TypeScript. Встроенные защитники, как написать свой с предикатом value is Type, как проверить, что объект относится к типу, функции утверждения с asserts и проверка данных unknown.
- Утверждения типаКлючевое слово as велит TypeScript считать значение другим типом. Это не приведение: во время выполнения ничего не преобразуется и не проверяется. Синтаксис as и угловых скобок, что разрешает компилятор, двойное утверждение через unknown и когда защитник типа подходит лучше.
- Оператор satisfiesОператор satisfies проверяет, что значение соответствует типу, не меняя выведенный тип значения. Что он делает, чем отличается от аннотации типа и от as (один и тот же объект, записанный тремя способами), как сочетается с as const и почему подходит для объектов конфигурации.
Классы
- КлассыКлассы TypeScript это классы JavaScript с типизированными полями, методами и конструкторами. Как работают объявления полей и strictPropertyInitialization, как типизировать this, геттеры и сеттеры, статические члены, implements и почему класс одновременно является типом.
- КонструкторыКак типизировать конструктор класса в TypeScript: типизированные и необязательные параметры, свойства-параметры вроде constructor(private name: string), порядок инициализации полей, перегрузки конструктора, вызов super в подклассах, приватные конструкторы и типы конструкторов с new.
- Модификаторы доступаВ TypeScript три модификатора доступа, public, private и protected, плюс readonly. Что разрешает каждый, почему private в TypeScript это проверка времени компиляции, а приватные поля JavaScript #private соблюдаются во время выполнения, и что выбрать.
- НаследованиеНаследование классов в TypeScript: extends и super, переопределение методов с совместимыми типами, ключевое слово override и noImplicitOverride, защищённые члены, переобъявление полей через declare и когда implements подходит лучше.
- Абстрактные классыАбстрактный класс в TypeScript это базовый класс, экземпляр которого нельзя создать и который может оставлять методы для реализации в подклассах. Абстрактные методы и свойства, шаблонный метод, абстрактные типы конструкторов и когда интерфейс подходит лучше.
- ДекораторыДекораторы это функции, которые оборачивают или заменяют члены класса через синтаксис @. Стандартные декораторы, которые TypeScript поддерживает без флагов (класса, метода, геттера, поля и accessor), фабрики декораторов, addInitializer и чем они отличаются от устаревших experimentalDecorators, на которых построены Angular и NestJS.
Дженерики
- ДженерикиДженерики позволяют функции, интерфейсу, типу или классу работать со многими типами, сохраняя связь между ними: то, что входит, определяет то, что выходит. Обобщённые функции, вывод аргументов типа, несколько параметров типа, обобщённые интерфейсы и классы, значения по умолчанию и когда дженерики не нужны.
- Ограничения дженериковОграничение дженерика, T extends Something, сужает круг типов, которые принимает параметр типа, и позволяет функции пользоваться тем, что гарантирует ограничение. extends с формами объектов и интерфейсами, K extends keyof T для безопасного доступа к свойствам, ограничения примитивами и ошибки, которые вы встретите.
Операторы типов
- Оператор keyofkeyof принимает объектный тип и даёт объединение имён его свойств. keyof с интерфейсами, keyof typeof для обычных объектов, типизированный доступ к свойствам через дженерики, сигнатуры индекса (string | number) и почему Object.keys возвращает string[].
- Доступ по индексуТип доступа по индексу читает тип свойства из другого типа: Person["age"] это number. T["key"], объединения ключей, T[keyof T], T[number] для элементов массива, индексы кортежей и (typeof arr)[number], чтобы превратить const-массив в объединение.
- Сопоставленные типыСопоставленный тип (mapped type) строит новый объектный тип, перебирая ключи: { [K in keyof T]: ... }. Синтаксис, модификаторы readonly и ? с + и -, переназначение ключей через as, фильтрация ключей и как написаны Partial, Readonly, Required, Pick и Record.
- Условные типыУсловный тип выбирает один из двух типов по результату проверки: T extends U ? X : Y. Синтаксис, как условные типы распределяются по объединениям (и как это отключить), извлечение типов через infer и как написать ReturnType самостоятельно.
- Шаблонные литеральные типыШаблонные литеральные типы строят строковые литеральные типы с тем же синтаксисом обратных кавычек, что и шаблонные строки JavaScript: `on${Capitalize<E>}`. Синтаксис, как перемножаются объединения, Uppercase и Capitalize, шаблоны вроде `${number}px`, геттеры в сопоставленных типах и разбор строк через infer.
- Брендированные типыБрендированный тип это примитив с невидимой меткой, например string & { readonly __brand: "UserId" }, чтобы UserId нельзя было передать туда, где ожидается OrderId. Как работают бренды, функции-конструкторы с проверкой, обобщённый помощник Brand, бренды на unique symbol и брендированные числа.
Служебные типы
- Служебные типыВсе встроенные служебные типы TypeScript в одном месте: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ReturnType, Awaited, строковые типы и другие, у каждого описание в одну строку и запускаемый пример.
- RecordRecord<K, V> это объектный тип, ключи которого имеют тип K, а все значения тип V. Record со строковыми ключами и с объединением ключей (каждый ключ обязателен), Partial<Record>, перебор Record с типизированными ключами, ловушка отсутствующего ключа и когда вместо него использовать сигнатуру индекса или Map.
- Partial и RequiredPartial<T> делает каждое свойство T необязательным, и это ровно тип объекта обновления или патча. Partial в функциях обновления, почему он поверхностный, как написать DeepPartial, ловушка явного undefined и противоположный ему Required<T>.
- OmitOmit<T, K> создаёт тип со всеми свойствами T, кроме ключей K. Omit с одним и несколькими ключами, переопределение типа свойства, удаление свойства во время выполнения, Omit против Exclude и Pick, почему Omit принимает несуществующие ключи, строгий Omit и Omit для типов объединения.
- PickPick<T, K> создаёт тип только из тех свойств T, ключи которых есть в K. Pick с одним или несколькими ключами, как он проверяет ключи, Pick против Omit, выбор из вложенных типов, типизированная функция pick() и выбор свойств по типу значения.
- readonly и ReadonlyМодификатор readonly и служебный тип Readonly<T> запрещают коду переприсваивать свойства. Свойства и поля классов readonly, Readonly<T>, readonly-массивы (readonly T[] и ReadonlyArray), ReadonlyMap и ReadonlySet, почему readonly поверхностный и действует только при компиляции, и как он соотносится с Object.freeze и as const.
- Exclude и ExtractExclude, Extract и NonNullable фильтруют члены типа объединения. Что каждый оставляет и убирает, как выбирать члены объединения по структуре, как они построены из условных типов и чем отличаются от Omit и Pick.
- ReturnType и ParametersReturnType, Parameters, ConstructorParameters, InstanceType и Awaited извлекают типы из функций, классов и промисов. Как использовать их с typeof, как получить тип результата асинхронной функции, что происходит с перегрузками и дженериками и как ReturnType построен через infer.
Циклы и коллекции
- ЦиклыВсе способы написать цикл в TypeScript и типы, которые даёт каждый: классический for, for...of по массивам, Map и строкам, for...in и его строковые ключи, forEach (без break и без await), типизированный перебор ключей объекта и while.
- Оператор switchОператор switch в TypeScript: синтаксис, как каждый case сужает тип-объединение, исчерпывающий switch, который не компилируется при пропущенном case, приём switch (true), проваливание и области видимости.
- MapКак пользоваться Map в TypeScript: создать типизированный Map<K, V>, почему get возвращает V | undefined, set, has и delete, перебор в порядке вставки, ключи-объекты, преобразование в объект и JSON и обратно, Map против объекта и Record и типизация array.map().
- СловарьВ TypeScript нет класса словаря или хеш-таблицы; поиск по ключу типизируют индексной сигнатурой, Record<K, V> или Map<K, V>. Разберём каждый вариант, проверку наличия ключа, добавление, удаление и перебор и зачем словарям noUncheckedIndexedAccess.
Асинхронность и ошибки
- ПромисыКак типизируются промисы в TypeScript: тип Promise<T>, типизация new Promise и resolve, как then меняет тип, почему catch даёт any, Promise.all с результатом-кортежем, типы результатов Promise.allSettled и обёртка API на колбэках в типизированный промис.
- Async/AwaitКак типизируются async и await в TypeScript: функция async возвращает Promise<T>, await его разворачивает, ошибки ловятся через try/catch, await верхнего уровня требует модуля ES, а также разница между ожиданием по одному, параллельным ожиданием и ловушкой forEach.
- Обработка ошибокОбработка ошибок в TypeScript: почему переменная catch имеет тип unknown, как сузить её через instanceof Error, выбрасывание ошибок, собственные классы ошибок с name и cause и приём с типом Result для ожидаемых ошибок.
- SleepВстроенного sleep в TypeScript нет, но его легко написать в одну строку: функция возвращает Promise<void>, который разрешается через setTimeout. Разберём, как ждать её через await, делать паузы в циклах, повторять попытки с задержкой, отменять sleep и почему в JavaScript нет блокирующего sleep.
Модули и инструменты
- МодулиЛюбой файл TypeScript с import или export на верхнем уровне является модулем. Именованный экспорт и экспорт по умолчанию, import type и export type, как настройка module выбирает между ES-модулями и CommonJS и почему node16 и nodenext требуют расширение .js в импортах.
- Пространства имёнNamespace в TypeScript объединяет значения и типы под одним именем и компилируется в обычный объект. Синтаксис, слияние пространств имён друг с другом, с функциями и классами, почему их заменили ES-модули и где они встречаются до сих пор: файлы объявлений и глобальное расширение.
- Файлы объявленийФайл .d.ts описывает типы JavaScript-кода, не содержа самого кода, а ключевое слово declare делает то же внутри файла .ts. Как генерируются файлы объявлений, где место пакетам @types, как типизировать модуль без типов и как declare global и расширение модулей дополняют существующие типы.
- Строгий режимstrict: true в tsconfig.json включает семейство проверок типов: noImplicitAny, strictNullChecks, strictPropertyInitialization и ещё пять. Что ловит каждая из них, как включить строгий режим в существующем проекте и какие полезные флаги в strict не входят.
- JSONJSON.parse возвращает any, поэтому TypeScript верит любому типу, который вы дадите результату. Как типизировать разобранный JSON, проверить его защитником типа, превратить пример JSON в интерфейс, импортировать файлы .json и что JSON.stringify делает с Date, Set и undefined.
Дальше
- Лучшие практикиВосемь привычек в TypeScript, которые предотвращают реальные ошибки: не выключать strict, использовать unknown вместо any, доверять выводу типов, предпочитать объединения enum, проверять конфигурацию через satisfies, моделировать состояние размеченными объединениями, избегать ! и as и делать данные readonly. К каждой прилагается запускаемый пример до и после.
- Вопросы на собеседовании25 вопросов по TypeScript для собеседования с короткими правильными ответами и кодом, от начального уровня до продвинутого: any и unknown, interface и type, дженерики, сужение типов, служебные типы, отображённые и условные типы, структурная типизация, tsconfig и TypeScript 7.