Границы и режимы

Граница — это любое место, где в программу приходят данные, которые вы не писали сами. Внутри вашего кода типы гарантирует компилятор. На границе они — лишь предположение о данных, которые вы не контролируете; t12n проверяет это предположение, чтобы вам не приходилось просто доверять.

Что детектится

В mode: 'auto' плагин по умолчанию распознаёт такие границы:

  • fetch().json(), fetch().text(), fetch().formData()
  • JSON.parse(...)
  • localStorage.getItem(...) и sessionStorage.getItem(...)
  • event.data на receiver’е с типом MessageEvent (postMessage, BroadcastChannel, Worker, WebSocket, EventSource)
  • касты as any и as unknown в объявлениях переменных
  • Vue/Nuxt-реактивность — см. Vue и Nuxt

Если у переменной слева стоит явная (не примитивная) аннотация типа, плагин оборачивает инициализатор. Типизированные параметры и возвраты функций тоже покрыты — см. Функции.

Набор можно сузить опцией boundaries, если нужны не все:

// vite.config.ts
t12n({ mode: 'auto', boundaries: ['fetch', 'json-parse'] })

Три режима

Плагин работает в одном из трёх режимов, задаваемых в Vite-конфиге:

РежимГде вставляются проверки
autoВсе границы из списка выше плюс любые типизированные параметры и возвраты функций
manualТолько там, где стоит Check<T>
offНичего — плагин неактивен (типы на этапе компиляции всё равно работают)

auto — по умолчанию. Оба режима используют один движок; отличается только то, что его запускает.

Когда тип невозможно проверить

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

// vite.config.ts
t12n({ mode: 'auto', onUnvalidated: 'warn' })
onUnvalidatedПоведение
'warn'По умолчанию — логировать каждую непроверяемую границу (файл:строка + какая граница) во время сборки
'error'Уронить сборку — для CI, чтобы запретить непроверяемые границы
'off'Молча пропускать

Типичное предупреждение:

[t12n] src/api.ts:12 — fetch().json() has a type t12n can't validate
       (any/unknown); left unchecked. Tighten the type or annotate Check<T>.

Лечится почти всегда тем, что границе дают конкретный тип (или Check<T>). Параметры функций в auto-режиме слишком многочисленны, чтобы предупреждать на каждом, — поэтому там сообщается только про явный Check<T>, который не удалось проверить.

Manual-режим — Check<T>

Иногда нужны явные проверки по запросу, а не сплошное авто-распознавание. Переключите плагин в manual:

// vite.config.ts
t12n({ mode: 'manual' })

Теперь обычные аннотации плагин не трогает. Чтобы запросить проверку, поставьте тип-маркер Check<T> — в присваивании, параметре или возвращаемом типе:

import type { Check } from 't12n'
import type { User } from './types'

// обычная аннотация: ничего не происходит
const a: User = somewhere()

// Check<User>: плагин видит маркер и вставляет проверку
const b: Check<User> = somewhereElse()

Check<T> на этапе компиляции — это просто T, без narrowing’а и бренда. Про «почему» — в Основных понятиях. Работает везде, где TypeScript принимает аннотацию типа.

Off-режим

t12n({ mode: 'off' })

Плагин неактивен. DOM-переопределения из t12n всё ещё работают на этапе компиляции — удобно, когда нужно только давление типов, с нулевой стоимостью в рантайме.