Лаборатория: типы, линтер, формат, runtime-вход и поведение
Оглавление · Инструменты · Проверки проекта
Задача: предсказать, какую ошибку заметит инструмент, затем получить конкретное свидетельство. Нужны TypeScript, схемы и функции.
Разные вопросы
| Средство | Что проверяет | Чего не доказывает |
|---|---|---|
| Typecheck | Согласованность с типами и config | Реальные неизвестные значения и бизнес-результат |
| Oxlint | Включённые правила анализа | Полную корректность программы |
| Oxfmt | Принятую запись текста | Верный смысл вычисления |
| Zod | Конкретное значение по схеме | Инварианты, не выраженные в схеме |
| Тест | Утверждение на заданном сценарии | Все возможные входы и реальную зависимость вместо mock |
Oxlint и Oxfmt имеют разные задачи. У проекта в .oxlintrc включены plugins typescript/react/nextjs и категория correctness=error; root lint работает по apps и packages с --deny-warnings. Oxfmt имеет отдельный ignore list. Check проверяет формат, обычный запуск пишет файлы; после записи прочитайте diff.
Подготовка временных файлов
Все команды ниже — из корня своего worktree, после штатной установки workspace.
Создайте apps/web/.local/tooling-lesson и пять файлов из следующих блоков.
.local исключён из Git; это не место для постоянных исходников. Импорт Zod будет
разрешаться через зависимости web. После упражнения удалите только созданные
файлы и пустой каталог урока.
1. type-error.mts
const count: number = "3";
console.log(count);
pnpm --filter @atmanki/web exec tsc --ignoreConfig --noEmit --strict \
--skipLibCheck --types node --target es2022 --module nodenext \
.local/tooling-lesson/type-error.mts
node apps/web/.local/tooling-lesson/type-error.mts
Компилятор должен сообщить несовместимость string и number. Node напечатает 3: аннотация удаляется, значение остаётся строкой. Вывод без кавычек не доказывает, что значение стало числом. --ignoreConfig относится к изолированной пробе TS 7; обычные проверки пакета используют его tsconfig и scripts.
2. lint-error.mts
export function inspectValue(value: number): number {
debugger;
return value;
}
pnpm exec oxlint --deny-warnings --deny no-debugger \
apps/web/.local/tooling-lesson/lint-error.mts
Ожидается диагностика no-debugger. Правило явно включено командой урока; не предполагаем, что оно обязано входить в текущую категорию проекта. Это допустимый JS/TS, но нарушает выбранное правило. Autofix и suppression требуют понимания причины; отключение диагностики не исправляет поведение.
3. format-error.mts
Блок показан как plain text, чтобы форматтер главы сохранил намеренное расхождение.
export const sample={value:1}
pnpm exec oxfmt --check apps/web/.local/tooling-lesson/format-error.mts
pnpm exec oxfmt apps/web/.local/tooling-lesson/format-error.mts
pnpm exec oxfmt --check apps/web/.local/tooling-lesson/format-error.mts
Первый check ожидает расхождение, второй — после форматирования — проходит. Сравните before/after: изменение пробелов и разделителей не делает value другим. В этом блоке исходная запись намеренно не соответствует стилю.
4. runtime-input.mts
import { z } from "zod";
const schema = z.object({ count: z.number().int().nonnegative() });
const input: unknown = { count: "3" };
console.log(schema.safeParse(input).success); // false
Тип unknown корректен, но конкретное значение не проходит runtime-схему.
safeParse возвращает результат проверки, не обязано бросать исключение:
процесс с выводом false может завершиться с exit code 0. Проверяйте результат,
а не только успешность запуска команды.
5. behavior.mts
export function total(values: readonly number[]): number {
return values.reduce((sum, value) => sum + value, 1);
}
Контракт упражнения: сумма массива, пустой массив даёт 0. Функция компилируется,
но ошибочный начальный аккумулятор нарушает контракт.
Создайте рядом behavior.test.mts:
import assert from "node:assert/strict";
import { test } from "node:test";
import { total } from "./behavior.mts";
test("sums values and uses zero for an empty input", () => {
assert.equal(total([2, 3]), 5);
assert.equal(total([]), 0);
});
node apps/web/.local/tooling-lesson/runtime-input.mts
node --test apps/web/.local/tooling-lesson/behavior.test.mts
Тест должен упасть. Поменяйте начальное значение на 0 и повторите его. Для отдельной typecheck-пробы с импортом .mts добавьте --allowImportingTsExtensions к параметрам выше. Проверка примера через Node test runner не меняет Jest-стек приложения: это временный урок, не новый UI-runner.
Что значит «прошло»
Для каждого файла запишите: команду, включённые правила, exit code, диагностику и наблюдаемый результат. Сравните предсказание с выполнением. Не ожидайте, что каждая ошибка будет обнаружена ровно одним средством: области могут пересекаться.
Изолированные файлы и явные CLI flags проверяют эти примеры. Они не подтверждают, что root scripts включают .local или весь учебный код; сами Markdown code blocks не проходят typecheck автоматически. Отдельные примеры извлекаются и проверяются при подготовке соответствующей главы.
Ежедневный цикл
Исходник схемы
flowchart LR Change["Маленькое изменение"] --> Target["Проверки затронутого контракта"] Target --> Diff["Чтение diff"] Diff --> Commit["Отдельный коммит"] Commit --> CI["CI на нужном ref"] CI --> Release["Публикация и проверка результата"]
Выбирайте проверки по изменению: ссылки/экспорт для docs, типы и тесты для контрактов, обе поверхности Storybook для компонента. Полный набор не требуется повторять после каждого абзаца; production-образы собирает CI.
Успех редактора, CLI, CI, публикации и живого сценария — разные стадии. Сравнивайте ref, версии, lockfile, переменные и рабочий каталог. Список реальных команд и границ покрытия хранится в главе проверок, расследование симптомов — в разборе проблем.