Live-режим
По умолчанию проверка срабатывает один раз, на границе, и отдаёт вам обычный объект. Ничто не мешает этому объекту «уехать» мгновением позже:
const user: User = await fetch('/api/me').then(r => r.json())
// проверено ✓
user.age = 'двадцать' // ✗ повторно не проверяется — это никто не поймает
Zod, Valibot и остальные работают так же: проверяют один раз и отдают обычный объект.
Live-режим держит тип живым всю жизнь объекта. Вместо одноразовой проверки
плагин эмитит guard, который валидирует так же, но возвращает рекурсивный
Proxy:
- запись значения не того типа в известное поле — ловится;
- запись поля, которого нет в типе, — ловится;
- удаление обязательного поля — ловится;
- вложенные объекты, массивы, record’ы и кортежи оборачиваются лениво при первом
чтении (identity сохраняется —
user.address === user.address).
const user: User = await fetch('/api/me').then(r => r.json())
user.age = 'двадцать' // 💥 ValidationError на "user.age" — поймано на лету
Как включить
Управляется опцией live у плагина:
// vite.config.ts
t12n({
mode: 'auto',
live: true, // форсим guard на каждой сборке
})
live | Поведение |
|---|---|
true | Эмитить Proxy-guard — мутации тоже под наблюдением |
false | Эмитить одноразовую проверку — только на границе |
| (не задано) | По умолчанию: true на dev-сервере (vite serve), false для прод-сборки |
Live ортогонален auto / manual / off: режим решает, куда ставятся
проверки, а live — продолжают ли они наблюдать после. Поставьте true,
чтобы следить за мутациями и в проде (в паре с обработчиком — см.
Ошибки и configure), или false, чтобы Proxy не
использовался никогда.
Цена
У этого есть реальная цена: каждый доступ к свойству guarded-объекта идёт через
trap. Поэтому по умолчанию Proxy работает только в dev, а в прод уходит дешёвая
компилируемая проверка. Proxy к тому же не переживает structured-clone границы
(postMessage, воркеры) — принимающая сторона просто заново оборачивает на
своей границе.