Начало работы
Настройка занимает минут пять: поставить пакет, добавить Vite-плагин и подключить типы в tsconfig. Дальше вы пишете обычный TypeScript, а t12n сам вставляет проверки.
Установка
npm i t12n
# также: pnpm add t12n · yarn add t12n · bun add t12n
В этом одном пакете есть всё: Vite-плагин, рантайм, DOM-переопределения и
тип-маркер Check<T>.
Подключение типов
Добавьте однострочную triple-slash-ссылку в любой амбиентный .d.ts, который
уже подключён в проекте (например env.d.ts или новый t12n.d.ts):
/// <reference types="t12n" />
Это подгрузит DOM-переопределения, которые помечают fetch().json(),
localStorage.getItem и подобное как Unvalidated<T>, и сделает тип-маркер
Check<T> доступным.
Предпочитайте ссылку, а не
"types": ["t12n"]вtsconfig.json— массивtypesтам выключает авто-подключение всех остальных амбиентных пакетов (node,vite/client, глобалы тестов…). Ссылка подгружает глобалы t12n без этого побочного эффекта. И это необязательно: рантайм-проверки работают и без неё — она лишь добавляет компайл-тайм-давление и глобальныйCheck<T>(его можно и простоimport type { Check } from 't12n').
Регистрация Vite-плагина
// vite.config.ts
import { defineConfig } from 'vite'
import t12n from 't12n/vite'
export default defineConfig({
plugins: [t12n()],
})
Это вся конфигурация — t12n() по умолчанию работает в режиме auto. Дальше
всё автоматически.
Первая проверка
Ничего вызывать или импортировать не нужно. Поставьте аннотацию типа на данные, которые приходят извне, — плагин видит границу, выводит схему из типа и вставляет проверку в нужной точке:
import type { User } from './types'
const user: User = await fetch('/api/me').then(r => r.json())
console.log(user.email)
На сборке это, по сути, превращается в:
import { __check } from 't12n/runtime'
const user = __check(
await fetch('/api/me').then(r => r.json()),
{ kind: 'object', properties: {
id: { kind: 'string' },
email: { kind: 'string' },
age: { kind: 'number' },
} }
)
Схема — это обычные данные, не Zod-вызовы: t12n ходит со своим валидатором и
без единой рантайм-зависимости. Форма с __check — наглядная модель; в
прод-сборке плагин компилирует каждый тип в отдельную функцию,
которая работает примерно в 8× быстрее Zod. Если ответ не совпал с User —
ValidationError с точным путём, ожидаемым типом и пришедшим значением.
Куда дальше
- Границы и режимы — что детектится и
auto/manual/off. - Vue и Nuxt — валидация
ref/reactive-состояния. - Функции — типизированные параметры и возвраты.
- Live-режим — держать тип под контролем после границы.
- Ошибки и configure — что делать при провале.
- Основные понятия и движок — как это всё устроено внутри.