Определение конструкторов типов
Кодируйте конструкторы типов с помощью обращений к интерфейсам
«Определение конструкторов типов» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Проблема HKT в TypeScript
- Определение конструкторов типов
- Облегчённый шаблон HKT
- Обобщённые функторы и мапперы