Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як тестувати самі типи: @ts-expect-error, expect-type і tsd?

Для бібліотек, спільних утиліт і складних генеріків типи - частина публічного API. Регресія в типі (функція почала повертати any, перестала ловити неправильний аргумент) - такий самий баг, як помилка в логіці. Звичайні тести її не помітять.

1. @ts-expect-error - перевірка, що помилка БУДЕ:

// @ts-expect-error - id має бути числом
loadUser('42');

Якщо рядок перестане бути помилкою, компілятор скаже Unused '@ts-expect-error' directive (TS2578). Так тестують, що тип забороняє неправильне використання.

Не плутати з @ts-ignore: той мовчки приховує будь-яку помилку і не скаже, якщо її вже немає. У коді застосунку @ts-ignore - майже завжди погана ідея; @ts-expect-error з поясненням чесніший.

2. expect-type - перевірка, що тип ТОЧНО такий:

import { expectTypeOf } from 'expect-type';

const row = queryBuilder.select('id', 'name').build();

expectTypeOf(row).toEqualTypeOf<{ id: number; name: string }>();
expectTypeOf(parseAge).returns.toEqualTypeOf<Result<number, AgeError>>();
expectTypeOf(useCart).toBeFunction();

Перевірка відбувається під час компіляції (tsc --noEmit). У Vitest той самий API вбудований (expectTypeOf), а режим vitest --typecheck запускає файли *.test-d.ts як типові тести.

3. tsd - окремий інструмент для .d.ts бібліотек: перевіряє типи з погляду споживача пакета (expectType, expectError). Використовує вбудовану версію компілятора, тож результат не залежить від TypeScript у проєкті.

Що тестувати:

  • виведення типів генеріків і перевантажень - результат має бути точним, а не any чи unknown;
  • заборонені виклики - неправильні аргументи мають давати помилку;
  • звуження: після type guard тип звужено правильно;
  • утиліти типів (DeepPartial, PathOf<T>) - на граничних випадках: never, об'єднання, порожні об'єкти, any.

Пастки:

  • перевірка «дорівнює» складніша, ніж здається: any сумісний з усім, тож наївна перевірка через присвоєння пропустить any. toEqualTypeOf враховує це;
  • тести типів запускаються лише в CI з tsc - Vite і esbuild при збиранні типи не перевіряють. Без кроку tsc --noEmit у CI типові тести нічого не ловлять.

Докладніше в документації: Коментарі @ts-expect-error

Схожі питання