0Pricing
TypeScript Academy · Урок

Определение конструкторов типов

Кодируйте конструкторы типов с помощью обращений к интерфейсам

«Определение конструкторов типов» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.

Именование конструкторов типов

Кодирование начинается с присвоения каждому конструктору типов уникального строкового идентификатора, называемого URI. URI — это тег, который заменяет конструктор там, где мы не можем передать сам конструктор.

type ArrayURI = "Array";
type OptionURI = "Option";
// Each container gets a unique string tag

Интерфейс реестра

Мы храним единый интерфейс, сопоставляющий каждый URI с конкретным типом, который он создаёт для заданного аргумента A. Этот интерфейс и есть реестр. Каждый ключ — это URI, а каждое значение — разрешённый тип.

interface URItoKind<A> {
  Array: Array<A>;
  Option: A | null;
}
// URItoKind<number>["Array"] is number[]

Поиск конструктора

Поскольку реестр индексируется по URI, применение конструктора превращается в доступ по индексу. Чтобы получить «массив, применённый к number», нужно обратиться к реестру по индексу.

type ArrayOfNumber = URItoKind<number>["Array"]; // number[]
type OptionOfString = URItoKind<string>["Option"]; // string | null

Объединение URIS

Множество допустимых тегов конструкторов — это просто ключи реестра. keyof URItoKind<unknown> даёт объединение всех зарегистрированных URI, которое мы называем URIS.

type URIS = keyof URItoKind<unknown>; // "Array" | "Option"

Слияние объявлений расширяет реестр

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

interface URItoKind<A> {
  Tree: { value: A; children: Array<A> };
}
// Now URIS also includes "Tree"

Модульные контейнеры

Благодаря слиянию контейнер, определённый в одном файле, регистрирует себя глобально. Любой, кто его импортирует, может использовать его URI в универсальных абстракциях. Именно так fp-ts добавляет опцию, контейнер с альтернативой, задачу и другие типы.

// file a.ts
interface URItoKind<A> { Either: { left: A } | { right: A } }
// file b.ts can now reference the "Either" URI

Фантомный носитель

Чтобы передавать «какой конструктор» как тип на уровне значений, экземпляры хранят свой URI в свойстве, часто в фантомном поле. Поле никогда не содержит реального значения, а лишь записывает тег для системы типов.

interface HasURI<F extends URIS> {
  readonly _URI: F;
}
// _URI records which constructor an instance is for

Сочетание URI с аргументом

Для применения конструктора нужны две вещи: URI F и тип аргумента A. Мы объединим их с помощью поиска, чтобы пара (F, A) разрешалась в конкретный тип через реестр.

type Apply<F extends URIS, A> = URItoKind<A>[F];

type A = Apply<"Array", number>;  // number[]
type B = Apply<"Option", string>; // string | null

Почему строки, а не конструкторы

Мы используем строки, потому что TypeScript может хранить их и сравнивать как типы-литералы, а также индексировать ими реестр. Мы не можем хранить конструктор Array как параметр типа, но можем сохранить литерал "Array" и найти его в реестре.

type Tag = "Array";
type Resolved = URItoKind<boolean>[Tag]; // boolean[]

Поиск — ключевой шаг

Этот доступ по индексу, URItoKind<A>[F], лежит в основе кодирования. Он превращает невозможное применение типа F<A> в допустимый поиск в реестре. В следующем уроке мы оформим его как Kind<F, A>.

type Kind<F extends URIS, A> = URItoKind<A>[F];

type X = Kind<"Array", number>; // number[]

Повторение основ

Теперь у вас есть все части: URI как теги, реестр URItoKind, сопоставляющий тег и аргумент с конкретным типом, URIS как объединение тегов и слияние объявлений для его расширения. Индексация реестра имитирует применение типа.

// URItoKind = registry, URIS = valid tags,
// URItoKind<A>[F] = "apply constructor F to A"

Быстрая проверка

Проверьте, насколько хорошо вы понимаете кодирование с помощью реестра.

Повторение

Вы научились кодировать конструкторы типов с помощью строк.

  • Каждый конструктор получает уникальный URI-тег.
  • URItoKind<A> сопоставляет теги с конкретными типами.
  • URIS — это объединение всех тегов, получаемое через keyof.
  • Слияние объявлений позволяет модулям регистрировать новые контейнеры.

Далее: оформление поиска в виде лёгкого шаблона Kind.

Часто задаваемые вопросы

Урок «Определение конструкторов типов» бесплатный?

Да — полный текст урока «Определение конструкторов типов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.

Чему я научусь в уроке «Определение конструкторов типов»?

Кодируйте конструкторы типов с помощью обращений к интерфейсам Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать TypeScript Academy?

Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Определение конструкторов типов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке TypeScript Academy?

Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Проблема HKT в TypeScript
  2. Определение конструкторов типов
  3. Облегчённый шаблон HKT
  4. Обобщённые функторы и мапперы
← Назад к TypeScript Academy