Границы и режимы
Граница — это любое место, где в программу приходят данные, которые вы не писали сами. Внутри вашего кода типы гарантирует компилятор. На границе они — лишь предположение о данных, которые вы не контролируете; 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 всё ещё работают на этапе
компиляции — удобно, когда нужно только давление типов, с нулевой стоимостью в
рантайме.