Основные понятия
Несколько идей объясняют, как работает t12n. Когда они в голове, остальной API читается легко.
Граница
Граница — это любое место, где в программу приходят данные, которые вы не
писали сами: ответ fetch, localStorage, postMessage, JSON.parse.
Внутри вашего кода типы гарантирует компилятор. На границе они — лишь предположение о данных, которые вы не контролируете. t12n проверяет это предположение, чтобы вам не приходилось ему просто доверять. Какие границы детектятся и как ими управлять — в разделе Границы и режимы.
Check<T> — тип-маркер
Check<T> — это identity-тип:
type Check<T> = T
На этапе компиляции ведёт себя ровно как T: ни narrowing’а, ни бренда, ничего
в рантайме. Плагин узнаёт аннотацию по имени и читает её как: «выведи схему для
T и оберни правую часть в проверку здесь».
const u: Check<User> = somewhere() // переменная
function f(u: Check<User>) { /* … */ } // параметр
function g(): Check<User> { /* … */ } // возвращаемый тип
Везде, где TypeScript принимает аннотацию, Check<T> работает. Плагин ещё и
переписывает эмитимый тип обратно на чистый T, чтобы дальнейшие потребители
видели нормальную форму. Это явный триггер для
manual-режима.
Unvalidated<T> — бренд границы
Два брендированных типа живут в пакете:
type Unvalidated<T> = T & { readonly [__unvalidated]: true }
type Validated<T> = T & { readonly [__validated]: true }
Бренд — unique symbol, подделать снаружи пакета нельзя. С загруженными
DOM-переопределениями (через /// <reference types="t12n" />) fetch().json() возвращает
Promise<Unvalidated<unknown>> — и компилятор не даёт использовать это как
что-то ещё, пока оно не прошло через проверку.
Auto-режим снимает бренд: когда t12n вставляет рантайм-проверку на
типизированной границе, результат трактуется как T (уже не Unvalidated<T>)
на последующих использованиях.
Три принципа
- Тип — источник правды. Схемы выводятся из ваших TypeScript-типов, так что нет второго определения, которое может разойтись с первым.
- Вы включаете проверку местом, а не вызовом. Что проверять — зависит от того, куда вы поставили аннотацию, а не от вызова функции.
- Падения громкие и точные. Когда данные не подходят, ошибка называет поле, ожидаемый тип и реальное значение и срабатывает на строке, где данные пришли.
Вот и вся модель. Что работает под капотом — вывод схемы и компилируемый валидатор — см. движок.