0Pricing
TypeScript Academy · Урок

Сообщения об ошибках в DSL на уровне типов

Выводите полезные сообщения об ошибках компиляции для пользователей DSL

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

Понятные ошибки в DSL на уровне типов

Самая сложная часть DSL на уровне типов — сделать сбои понятными. Необработанные ошибки never или «несовместимо с типом» сбивают пользователей с толку. Мы выводим описательные ошибки с помощью типов ошибок с маркером и специально сформированных сообщений never.

Проблема с never

Когда проверка завершается типом never, компилятор сообщает: «Аргумент типа X не может быть присвоен типу never», но не объясняет пользователю, почему. Можно сделать лучше.

Типы ошибок с маркером

Вместо обычного never возвращайте уникальный тип ошибки, содержащий в своём типе строку с понятным человеку сообщением.

type TypeError<Msg extends string> = {
  readonly __error: Msg;
};

type E = TypeError<"Column 'foo' does not exist">;

Возврат ошибок из проверки

Валидатор возвращает либо тип корректного значения, либо тип ошибки с маркером, описывающий проблему. Проверка «содержит точку» является шаблоном строкового литерала с обратными кавычками (в реальном коде); здесь мы обозначаем её как HasDot.

// HasDot<S> is the backtick pattern: any text, ".", any text.

type Validate<S extends string> =
  S extends HasDot
    ? S
    : TypeError<"Path must contain a dot, e.g. user.name">;

Принудительный вывод ошибки

Ограничьте параметр так, чтобы передача значения, несовместимого с маркером ошибки, выводила сообщение. Тип ошибки появляется непосредственно в выводе компилятора.

declare function path<S extends string>(
  p: Validate<S> extends TypeError<infer M> ? TypeError<M> : S
): void;

path("oops");
// Error message includes: __error: "Path must contain a dot..."

Различение нескольких ошибок

Разные сбои возвращают разные сообщения, поэтому пользователи получают конкретные рекомендации вместо одного общего отказа. HasDot снова является шаблоном строкового литерала с обратными кавычками для проверки «содержит точку».

type Check<S extends string> =
  S extends "" ? TypeError<"Path cannot be empty">
  : S extends HasDot ? S
  : TypeError<"Missing dot separator">;

never с дополнительными возможностями

Другой приём связывает позицию значения с литеральным сообщением, чтобы оно отображалось при наведении. Объедините тип, вызвавший проблему, с помеченным объектом.

type Invalid<M extends string> = { error: M } & never;
// using never keeps it unassignable while the label hints the cause

Ошибки в цепочечных DSL

В цепочечном DSL пусть следующий недопустимый шаг возвращает тип с маркером ошибки вместо корректного этапа, чтобы редактор показывал сообщение непосредственно в месте ошибки.

interface Stage {
  // calling done() before where() yields a labeled error
  done(): TypeError<"Call .where() before .done()">;
}

Краткие сообщения

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

Проверка ошибок

Пишите тесты на уровне типов, которые проверяют наличие маркера ошибки для заведомо некорректных входных данных, чтобы рефакторинг незаметно не ухудшил удобство работы разработчика.

type Expect<T extends true> = T;
type _t = Expect<Validate<"oops"> extends TypeError<any> ? true : false>;

Почему это важно

Качество DSL определяется качеством его ошибок. Типы ошибок с маркером превращают неясные сбои never в самообъясняющие сообщения, значительно улучшая работу с Вашим API на уровне типов.

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

Подтвердите, насколько хорошо Вы поняли сообщения об ошибках на уровне типов.

Итоги

Чтобы DSL на уровне типов было удобно использовать, заменяйте отдельный never на типы ошибок с маркером, содержащие понятные сообщения. Валидаторы возвращают либо корректный тип, либо конкретный маркер ошибки; ограничение параметров выводит сообщение в результатах компилятора. Сообщения должны быть краткими, и их необходимо проверять тестами.

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

Урок «Сообщения об ошибках в DSL на уровне типов» бесплатный?

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

Чему я научусь в уроке «Сообщения об ошибках в DSL на уровне типов»?

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

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

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

Сколько времени занимает урок «Сообщения об ошибках в DSL на уровне типов»?

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

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

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

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

  1. Что такое DSL на уровне типов
  2. Проектирование плавного DSL запросов
  3. Проверка входных данных во время компиляции
  4. Сообщения об ошибках в DSL на уровне типов
← Назад к TypeScript Academy