Основы программирования на TypeScript

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

1. Введение в TypeScript: установка окружения и базовые типы данных

Введение в TypeScript: установка окружения и базовые типы данных

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

Что такое TypeScript и зачем он нужен?

TypeScript (часто сокращают как TS) — это язык программирования, разработанный компанией Microsoft. Главное, что нужно запомнить: TypeScript — это надмножество JavaScript.

Это означает, что любой валидный код на JavaScript (JS) также является валидным кодом на TypeScript. Однако TS добавляет поверх JS новые возможности, главной из которых является статическая типизация.

!TypeScript включает в себя все возможности JavaScript, расширяя их дополнительными инструментами.

Проблема JavaScript

JavaScript — язык с динамической типизацией. Это значит, что переменная, которая только что хранила число, через секунду может начать хранить строку, и интерпретатор не увидит в этом проблемы до момента запуска кода. Это часто приводит к ошибкам, которые обнаруживаются уже пользователями в работающем приложении.

Решение TypeScript

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

> TypeScript не исполняется браузером напрямую. Он транспилируется (компилируется) в обычный JavaScript, который уже понятен браузерам и Node.js.

Установка окружения

Чтобы начать писать на TypeScript, нам понадобятся два инструмента:

  • Node.js — среда выполнения JavaScript (она включает в себя менеджер пакетов npm).
  • Компилятор TypeScript — программа, которая превращает TS-код в JS-код.
  • Шаг 1: Установка Node.js

    Если у вас еще не установлен Node.js, скачайте LTS-версию с официального сайта и установите её. Чтобы проверить, что установка прошла успешно, откройте терминал (командную строку) и введите:

    Вы должны увидеть версии установленных программ.

    Шаг 2: Установка TypeScript

    Мы установим TypeScript глобально, чтобы иметь доступ к нему из любой папки на компьютере. Введите в терминале следующую команду:

    После завершения установки проверьте версию компилятора:

    Команда tsc расшифровывается как TypeScript Compiler.

    Ваша первая программа

    Давайте создадим простейшую программу, чтобы понять процесс работы.

  • Создайте новую папку для проекта и откройте её в редакторе кода (рекомендуется VS Code).
  • Создайте файл с именем hello.ts. Обратите внимание на расширение .ts.
  • Напишите следующий код:
  • Здесь мы видим первое отличие от JS: после названия переменной message мы поставили двоеточие и указали тип string (строка).

  • Теперь нам нужно превратить этот файл в JavaScript. Откройте терминал в папке с файлом и введите:
  • Посмотрите в папку. Там появился новый файл hello.js. Если вы откроете его, то увидите обычный JavaScript код (часто без указания типов, так как JS их не поддерживает).
  • Запустите полученный файл:
  • В консоли вы увидите: Привет, мир TypeScript!.

    Базовые типы данных

    Система типов — это сердце TypeScript. Давайте разберем основные примитивы, с которыми вы будете работать каждый день. Синтаксис объявления типа выглядит так:

    Boolean (Логический тип)

    Самый простой тип данных, который имеет всего два значения: true (истина) или false (ложь).

    Number (Число)

    В TypeScript, как и в JavaScript, все числа являются числами с плавающей точкой. Тип number используется и для целых чисел, и для дробных.

    String (Строка)

    Для работы с текстовыми данными используется тип string. Можно использовать двойные кавычки ", одинарные ' или обратные кавычки ` ` для шаблонов.

    Array (Массив)

    Массивы можно типизировать двумя способами. Результат абсолютно одинаковый, выбор зависит от стиля вашей команды.

    Способ 1: Использование типа элемента, за которым следуют квадратные скобки [].

    Способ 2: Использование обобщенного типа (Generics) Array<type>.

    Если вы попытаетесь добавить строку в такой массив, TypeScript выдаст ошибку.

    Tuple (Кортеж)

    Иногда нам нужно создать массив с фиксированным количеством элементов, типы которых известны, но не обязательно одинаковы. Такая структура называется Кортеж.

    Например, мы хотим хранить пару «имя пользователя» (строка) и «возраст» (число):

    !Кортеж (Tuple) строго определяет порядок и типы данных в массиве фиксированной длины.

    Any (Любой тип)

    Иногда мы не знаем, какой тип данных придет (например, от сторонней библиотеки или от пользователя). В таких случаях можно использовать тип any.

    Важно: Старайтесь избегать использования any. Используя его, вы отключаете проверку типов для этой переменной, по сути возвращаясь к обычному JavaScript. Злоупотребление any` лишает смысла использование TypeScript.

    Void, Null и Undefined

    * Void обычно используется как возвращаемый тип функций, которые ничего не возвращают. * Null и Undefined соответствуют своим аналогам из JavaScript. Сами по себе они редко используются как типы переменных, но часто участвуют в объединениях типов (о которых мы поговорим в следующих статьях).

    Вывод типов (Type Inference)

    TypeScript достаточно умен. Во многих случаях вам не нужно явно указывать тип — компилятор сам поймет его по значению, которое вы присваиваете.

    Это называется выводом типов. Хорошей практикой считается позволять TypeScript самому выводить типы там, где это очевидно, чтобы код оставался чистым и читаемым.

    Заключение

    Сегодня мы заложили фундамент для изучения TypeScript. Мы установили окружение, написали первую программу и разобрали базовые кирпичики данных. Главное преимущество, которое вы получили уже сейчас — это безопасность. TypeScript страхует вас от глупых ошибок, связанных с типами данных.

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

    2. Структурирование данных: интерфейсы, Type Aliases и Enums

    Структурирование данных: интерфейсы, Type Aliases и Enums

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

    Сегодня мы разберем три ключевых инструмента TypeScript, которые позволяют описывать форму объектов и создавать собственные типы данных: Interfaces (Интерфейсы), Type Aliases (Псевдонимы типов) и Enums (Перечисления).

    Интерфейсы (Interfaces)

    В TypeScript интерфейс — это способ определить контракт для объекта. Это своего рода «чертеж», который говорит: «Если ты хочешь быть объектом типа User, ты обязан иметь вот такие свойства».

    !Интерфейс работает как архитектурный чертеж: он описывает обязательную структуру, по которой создается реальный объект

    Объявление интерфейса

    Для создания интерфейса используется ключевое слово interface. Принято называть интерфейсы с большой буквы.

    Если мы попытаемся не указать свойство email или задать age как строку, TypeScript немедленно подсветит ошибку. Это гарантирует, что объект всегда соответствует ожидаемой структуре.

    Необязательные свойства

    Иногда объект может иметь свойства, которые не являются обязательными. Например, у пользователя может не быть номера телефона. Для этого используется знак вопроса ? после названия свойства.

    Свойства только для чтения (Readonly)

    Некоторые данные не должны изменяться после создания объекта (например, id пользователя). Для этого используется модификатор readonly.

    Псевдонимы типов (Type Aliases)

    Второй способ создания типов в TypeScript — это использование ключевого слова type. На первый взгляд они очень похожи на интерфейсы, но имеют более широкую область применения.

    Базовый синтаксис

    Главная сила Type Aliases: Объединения (Union Types)

    В отличие от интерфейсов, type позволяет создавать типы, которые могут быть «или тем, или этим». Это делается с помощью символа вертикальной черты |.

    Представьте, что у нас есть ID, который может приходить с сервера либо как число, либо как строка.

    Пересечения (Intersection Types)

    Мы можем комбинировать несколько типов в один, используя символ амперсанда &.

    Interface или Type: что выбрать?

    Это один из самых частых вопросов на собеседованиях. Давайте сравним их.

    | Характеристика | Interface | Type Alias | | :--- | :--- | :--- | | Описание объектов | Да | Да | | Описание функций | Да | Да | | Union Types (A &#124; B) | Нет | Да | | Примитивы (string, number) | Нет | Да | | Расширение (Extends) | Через extends | Через & | | Слияние деклараций | Да (автоматически) | Нет (ошибка дубликата) |

    Слияние деклараций (Declaration Merging) — уникальная фишка интерфейсов. Если вы объявите один и тот же интерфейс дважды, TypeScript объединит их в один.

    > Совет: Используйте interface для описания формы объектов (особенно если вы пишите библиотеку, которую будут расширять другие разработчики). Используйте type для создания объединений (Union), кортежей или псевдонимов для примитивов.

    Перечисления (Enums)

    Enum (Enumeration) — это способ задать набор именованных констант. Это делает код более читаемым и защищает от опечаток.

    !Enums работают как переключатель с фиксированным набором состояний, где каждому имени соответствует значение

    Числовые Enums

    По умолчанию элементы перечисления получают значения начиная с 0.

    Вы можете изменить начальное значение, и остальные пересчитаются автоматически:

    Строковые Enums

    Для отладки часто удобнее использовать строковые значения, так как в логах вы увидите понятный текст, а не просто цифру.

    Когда использовать Enums?

    Используйте Enums, когда у вас есть ограниченный набор вариантов выбора: * Статусы заказа (Pending, Shipped, Delivered) * Дни недели * Цвета светофора * Уровни доступа

    Практический пример: Система задач

    Давайте объединим полученные знания и опишем структуру данных для простого приложения «Список задач».

    В этом примере мы видим, как гармонично сочетаются все три конструкции. Enum ограничивает возможные статусы, Type дает гибкость в формате идентификатора, а Interface собирает всё это в понятную структуру объекта.

    Заключение

    Сегодня мы сделали огромный шаг вперед. От простых типов мы перешли к моделированию реальных данных. Вы узнали:

  • Как описывать объекты с помощью Interfaces.
  • Как создавать гибкие типы и объединения с помощью Type Aliases.
  • Как использовать Enums для работы с наборами констант.
  • Эти инструменты составляют 80% того, что вы будете использовать при написании типов в повседневной работе. В следующей статье мы поговорим о том, как типизировать функции — основной строительный блок любого приложения на JavaScript и TypeScript.

    3. Функции и классы: типизация и объектно-ориентированный подход

    Функции и классы: типизация и объектно-ориентированный подход

    Добро пожаловать в третью часть курса «Основы программирования на TypeScript». В предыдущих статьях мы научились настраивать рабочее окружение и описывать структуры данных с помощью интерфейсов и псевдонимов типов. Теперь у нас есть «кирпичики» данных, но нам не хватает «цемента», чтобы построить из них полноценное приложение. Этим связующим звеном является логика.

    В JavaScript и TypeScript логика в основном живет в двух конструкциях: функциях и классах. Сегодня мы узнаем, как сделать функции безопасными, зачем нужны модификаторы доступа в классах и как TypeScript превращает стандартный объектно-ориентированный подход в мощный инструмент архитектуры.

    Типизация функций

    Функции — это фундаментальные строительные блоки любого приложения. В JavaScript функции могут принимать что угодно и возвращать что угодно. TypeScript наводит здесь строгий порядок.

    Параметры и возвращаемое значение

    Чтобы типизировать функцию, нам нужно ответить на два вопроса: что она принимает на вход и что отдает на выходе.

    В этом примере:

  • x и y обязаны быть числами.
  • : number после круглых скобок указывает, что результат работы функции тоже будет числом.
  • Если функция ничего не возвращает (например, просто выводит лог в консоль), используется тип void.

    !Визуализация принципа строгой типизации входных и выходных данных функции.

    Необязательные параметры и параметры по умолчанию

    В JavaScript все параметры функции опциональны. В TypeScript, если вы описали параметр, он становится обязательным. Чтобы сделать его необязательным, мы снова используем знак вопроса ?, как и в интерфейсах.

    Также можно задать значение по умолчанию. В этом случае указывать тип необязательно — TypeScript выведет его сам.

    REST-параметры (Остаточные параметры)

    Иногда мы не знаем заранее, сколько аргументов передаст пользователь. Например, функция суммирования всех переданных чисел. Для этого используется оператор ... (rest operator), и такой параметр всегда типизируется как массив.

    Перегрузка функций (Function Overloads)

    Это продвинутая концепция, которая часто пугает новичков, но она очень полезна. Представьте функцию, которая может принимать либо строку, либо число. Если пришла строка — она возвращает строку. Если число — возвращает число.

    В TypeScript это реализуется через перегрузку: мы сначала пишем несколько сигнатур (вариантов использования), и только потом саму реализацию.

    Классы и Объектно-Ориентированное Программирование (ООП)

    TypeScript полностью поддерживает классы из стандарта ES6 и добавляет к ним мощную систему типов и модификаторов доступа, делая работу похожей на такие языки, как C# или Java.

    Анатомия класса

    Класс — это чертеж для создания объектов. Он описывает свойства (данные) и методы (поведение).

    Модификаторы доступа

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

    Существует три основных модификатора:

  • public (по умолчанию): Доступ открыт всем и отовсюду.
  • private: Доступ есть только внутри самого класса. Даже наследники не видят эти свойства.
  • protected: Доступ есть внутри класса и внутри классов-наследников.
  • !Аналогия модификаторов доступа на примере дома.

    Рассмотрим пример:

    Сокращенная инициализация (Parameter Properties)

    В TypeScript есть очень удобный синтаксис, позволяющий объявлять свойства и присваивать им значения прямо в аргументах конструктора. Это избавляет от написания лишнего кода.

    Вместо этого:

    Можно написать так:

    Результат абсолютно одинаковый, но второй вариант намного лаконичнее.

    Наследование

    Классы могут наследовать свойства и методы других классов с помощью ключевого слова extends. Это позволяет создавать иерархии и повторно использовать код.

    Реализация интерфейсов (Implements)

    В прошлой статье мы изучали интерфейсы. Классы могут гарантировать соблюдение интерфейса с помощью ключевого слова implements.

    Это мощный инструмент для создания архитектуры: вы сначала описываете контракты (интерфейсы), а затем создаете классы, которые эти контракты исполняют.

    Абстрактные классы

    Иногда нам нужен базовый класс, который служит только основой для других классов, но сам по себе не должен использоваться для создания объектов. Такие классы называются абстрактными.

    Абстрактный класс может содержать:

  • Реализованные методы (обычные).
  • Абстрактные методы (без реализации, только описание типа).
  • Заключение

    Сегодня мы значительно расширили наш арсенал. Мы узнали: * Как строго типизировать функции, включая параметры и возвращаемые значения. * Как использовать перегрузку функций для гибкости. * Как создавать классы и защищать данные с помощью модификаторов private и protected. * Как работает наследование и реализация интерфейсов.

    Теперь вы можете не только описывать данные, но и создавать надежную бизнес-логику, защищенную от неправильного использования. В следующей статье мы разберем одну из самых сложных, но интересных тем TypeScript — Generics (Обобщения), которые позволят нам писать универсальный код, работающий с разными типами данных без потери строгой типизации.

    4. Продвинутые возможности: обобщения (Generics) и утилитарные типы

    Продвинутые возможности: обобщения (Generics) и утилитарные типы

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

    Однако, по мере роста ваших приложений, вы могли столкнуться с одной проблемой: дублирование кода. Иногда нам нужно написать функцию или класс, которые делают одно и то же, но для разных типов данных. Копировать код и менять в нем только типы — плохая практика. Использовать any — значит потерять безопасность.

    Сегодня мы изучим решение этой проблемы — Generics (Обобщения). А также рассмотрим Utility Types (Утилитарные типы) — встроенные инструменты TypeScript, которые избавят вас от рутинного описания типов.

    Обобщения (Generics): гибкость без потери контроля

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

    Но как типизировать это в TypeScript? Если мы напишем конкретный тип, функция станет бесполезной для других типов:

    Теперь мы не можем передать туда строку. Можно использовать any:

    Но тогда мы теряем информацию о типе. Если мы передадим строку, TypeScript «забудет» об этом, и на выходе мы получим просто any. Мы не сможем безопасно использовать методы строки, такие как .toUpperCase().

    Переменная для типов

    Здесь на сцену выходят Generics. Это способ создать «переменную», в которую мы запишем тип в момент использования функции. Обычно для этого используют букву T (от слова Type), но имя может быть любым.

    Давайте разберем этот синтаксис:

  • <T> после имени функции объявляет, что функция является обобщенной и использует параметр типа T.
  • arg: T говорит, что аргумент будет этого типа.
  • : T говорит, что функция вернет значение того же самого типа.
  • !Схема работы Generics: одна логика обрабатывает разные типы данных, сохраняя их идентичность.

    Теперь мы можем использовать эту функцию так:

    Generics в массивах и стрелочных функциях

    Вы уже встречались с обобщениями, когда работали с массивами. Запись Array<number> — это и есть использование встроенного Generic-типа Array.

    Давайте напишем функцию, которая принимает массив любых элементов и возвращает первый элемент:

    Обратите внимание: <T> в стрелочной функции ставится перед скобками аргументов.

    Обобщенные интерфейсы

    Generics работают не только с функциями, но и с интерфейсами. Это невероятно полезно при описании ответов от сервера (API).

    Представьте, что ваш сервер всегда присылает ответ в формате:

    Мы можем описать это одним универсальным интерфейсом:

    Теперь UserResponse автоматически знает, что внутри data лежит User, а ProductResponse ожидает Product. Нам не пришлось писать два разных интерфейса для ответов.

    Ограничения обобщений (Generic Constraints)

    Иногда мы хотим, чтобы наш Generic принимал не любой тип, а только тот, который обладает определенными свойствами. Для этого используется ключевое слово extends.

    Допустим, мы хотим написать функцию, которая выводит в консоль длину аргумента.

    Тип T может быть числом или булевым значением, у которых нет свойства .length. Нам нужно ограничить T, сказав: «Я приму любой тип, но только если у него есть длина».

    Утилитарные типы (Utility Types)

    TypeScript поставляется с набором встроенных типов, которые позволяют трансформировать уже существующие типы. Это избавляет от необходимости переписывать интерфейсы вручную. Рассмотрим самые популярные из них.

    Partial<T>

    Делает все свойства типа T необязательными.

    Сценарий: У вас есть форма редактирования профиля пользователя. Пользователь может изменить только имя, или только email, или всё сразу. Вам не нужно создавать отдельный тип UpdateUserDto.

    Required<T>

    Противоположность Partial. Делает все свойства обязательными (даже те, что были помечены ?).

    Readonly<T>

    Делает все свойства типа T доступными только для чтения. Это полезно для защиты объектов конфигурации или состояния (state) в Redux.

    Pick<T, K>

    Создает новый тип, выбирая только указанные свойства K из типа T.

    Сценарий: У вас есть огромный объект пользователя, но для отображения карточки на сайте вам нужны только имя и аватар.

    Omit<T, K>

    Противоположность Pick. Создает новый тип, исключая указанные свойства K из типа T.

    Сценарий: Вы хотите передать объект пользователя на клиент, но вам категорически нельзя передавать хеш пароля.

    Record<K, T>

    Используется для описания объектов, где ключи имеют тип K, а значения — тип T. Это более строгая и удобная альтернатива индексным сигнатурам.

    Сценарий: Нам нужно хранить словарь, где ключом является название страницы, а значением — информация о ней.

    Заключение

    Сегодня мы перешли от простого описания типов к мета-программированию.

  • Generics позволяют писать универсальный код, который работает с разными типами данных, не теряя строгой типизации. Это как переменные, но для типов.
  • Constraints (extends) позволяют ограничивать Generics, требуя наличия определенных свойств.
  • Utility Types (Partial, Pick, Omit и др.) — это мощный инструментарий для трансформации типов, который спасает от дублирования кода.
  • Освоение этих инструментов отличает новичка от уверенного разработчика на TypeScript. В следующей, заключительной статье курса, мы рассмотрим декораторы и настройку конфигурации tsconfig.json для профессиональной разработки.

    5. Конфигурация tsconfig, модули и интеграция с современными проектами

    Конфигурация tsconfig, модули и интеграция с современными проектами

    Добро пожаловать в заключительную статью курса «Основы программирования на TypeScript». Мы прошли долгий путь: от установки Node.js до написания сложных обобщенных типов (Generics). Теперь вы умеете писать безопасный и надежный код.

    Однако в реальной разработке код не существует в вакууме. Он живет внутри проектов, взаимодействует с другими файлами, собирается сборщиками и проверяется линтерами. Сегодня мы разберем, как управлять поведением компилятора через tsconfig.json, как организовать код с помощью модулей, что такое декораторы и как интегрировать TypeScript в современный стек технологий.

    Файл конфигурации tsconfig.json

    Когда мы запускали команду tsc filename.ts в первых уроках, мы использовали настройки по умолчанию. Но для серьезного проекта этого недостаточно. Нам нужно указать компилятору, куда складывать готовые файлы, насколько строгим быть при проверке и в какую версию JavaScript превращать наш код.

    Все эти настройки хранятся в файле tsconfig.json. Это «паспорт» вашего проекта.

    !Файл tsconfig.json работает как пульт управления компилятором, определяя правила игры для всего проекта.

    Создание конфигурации

    Чтобы создать этот файл автоматически, откройте терминал в папке вашего проекта и введите:

    Вы увидите, что в папке появился файл tsconfig.json с огромным количеством настроек, большинство из которых закомментированы. Давайте разберем самые важные из них.

    Основные опции компилятора

    Настройки находятся внутри объекта compilerOptions. Вот те, которые вы будете использовать чаще всего:

    #### 1. target Эта опция определяет, в какую версию стандарта ECMAScript (JavaScript) будет скомпилирован ваш TS-код.

    * "target": "es5": Максимальная совместимость. Код будет работать даже в старых браузерах, но итоговый файл будет больше и сложнее. * "target": "es6" (или es2015): Стандарт для большинства современных веб-проектов. * "target": "esnext": Самая свежая версия. Используйте, если вы уверены, что среда выполнения (например, последняя версия Node.js) поддерживает все новинки.

    #### 2. module Определяет систему модулей для итогового файла.

    * "commonjs": Стандарт для Node.js (использует require). * "esnext": Использует современные import и export. Это лучший выбор, если вы используете сборщики вроде Webpack или Vite.

    #### 3. outDir и rootDir Эти настройки помогают организовать структуру папок, чтобы исходный код не смешивался со скомпилированным.

    * "rootDir": "./src": Компилятор будет искать TS-файлы в папке src. * "outDir": "./dist": Готовые JS-файлы будут складываться в папку dist (distribution).

    #### 4. strict Это «режим строгого начальника». Если установить "strict": true, TypeScript включит сразу несколько проверок, включая:

    * noImplicitAny: Запрещает использование типа any там, где тип не указан явно. * strictNullChecks: Запрещает присваивать null или undefined переменным, которые не ожидают этого явно.

    > Рекомендация: Всегда включайте "strict": true в новых проектах. Это заставляет писать более качественный код с самого начала.

    Модули в TypeScript

    В современном JavaScript и TypeScript принято разбивать код на множество небольших файлов — модулей. Это упрощает поддержку и тестирование.

    TypeScript полностью поддерживает стандарт ES Modules (ESM). Любой файл, содержащий import или export, считается модулем.

    Экспорт (Export)

    Чтобы сделать переменную, функцию или класс доступными для других файлов, используйте ключевое слово export.

    Импорт (Import)

    Чтобы использовать код из другого файла, используйте import.

    Экспорт по умолчанию (Default Export)

    Каждый модуль может иметь один «главный» экспорт. Это удобно для классов или компонентов.

    Декораторы (Decorators)

    В конце прошлой статьи мы упоминали декораторы. Это продвинутая возможность, которая пришла в TypeScript из мира таких языков, как Java и Python, и широко используется в фреймворках типа Angular и NestJS.

    Декоратор — это специальная функция, которая может быть присоединена к объявлению класса, метода, свойства или параметра. Декораторы позволяют модифицировать поведение класса или добавить к нему метаданные.

    Чтобы использовать декораторы, нужно включить опцию в tsconfig.json:

    Синтаксис

    Декораторы используют символ @. Давайте напишем простой декоратор, который логирует создание класса.

    !Декоратор работает как обертка, добавляющая дополнительную функциональность или логику к существующему коду без изменения его внутренней структуры.

    Декораторы — мощный инструмент метапрограммирования, но в обычных приложениях (React, Vue) вы будете встречаться с ними редко, если только не используете MobX или NestJS.

    Интеграция с инструментами разработки

    TypeScript редко работает в одиночку. В современном проекте он является частью большой экосистемы.

    Линтеры (ESLint)

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

    Существует специальный плагин @typescript-eslint, который позволяет ESLint понимать TS-код. Связка TS + ESLint — это золотой стандарт качества.

    Сборщики (Webpack, Vite)

    Браузеры не умеют исполнять TypeScript напрямую (пока что). Поэтому нам нужен инструмент, который:

  • Превратит TS в JS.
  • Соберет все модули в один или несколько файлов (bundle).
  • Оптимизирует код.
  • Популярные инструменты вроде Vite или Webpack имеют встроенную поддержку TypeScript. Обычно при создании проекта (например, через npm create vite@latest) вам сразу предложат выбрать TypeScript, и вся конфигурация будет создана автоматически.

    Prettier

    Если TypeScript следит за смыслом, а ESLint за правилами, то Prettier следит за красотой. Он автоматически расставляет запятые, точки с запятой и отступы. Настройте его один раз, и вам больше никогда не придется спорить с коллегами о том, ставить пробел перед скобкой или нет.

    Заключение курса

    Поздравляю! Вы завершили курс «Основы программирования на TypeScript».

    Давайте вспомним, чему мы научились:

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

    Ваше путешествие только начинается. Впереди вас ждут глубокие дебри условных типов (Conditional Types), магия infer и работа с популярными фреймворками. Но фундамент, который вы заложили здесь, позволит вам уверенно чувствовать себя в любом современном проекте.

    Удачи в коде!