타입 검사
Vitest는 expectTypeOf 또는 assertType 구문을 사용하여 타입 테스트를 작성할 수 있도록 지원합니다. 기본적으로 *.test-d.ts 파일 내의 모든 테스트는 타입 테스트로 간주되지만, typecheck.include 설정 옵션을 통해 이 동작을 변경할 수 있습니다.
Vitest는 내부적으로 설정에 따라 tsc 또는 vue-tsc를 호출하고 그 결과를 파싱합니다. Vitest는 소스 코드에서 타입 오류를 발견하면 이를 보고합니다. typecheck.ignoreSourceErrors 설정 옵션을 사용하여 이 보고를 비활성화할 수 있습니다.
Vitest는 이 파일들을 직접 실행하지 않고 컴파일러에 의한 정적 분석만 수행한다는 점을 유의하십시오. 이는 동적 이름이나 test.each 또는 test.for를 사용하는 경우 테스트 이름이 평가되지 않고 그대로 표시됨을 의미합니다.
WARNING
Vitest 2.1 이전에는 typecheck.include가 include 패턴을 재정의하여 런타임 테스트가 실제로 실행되지 않고 타입 검사만 이루어졌습니다.
Vitest 2.1부터는 include와 typecheck.include가 겹칠 경우 Vitest는 타입 테스트와 런타임 테스트를 별도의 항목으로 보고합니다.
--allowOnly 및 -t와 같은 CLI 플래그 또한 타입 검사에서 지원됩니다.
import { assertType, expectTypeOf } from 'vitest';
import { mount } from './mount.js';
test('my types work properly', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name은 문자열입니다.
assertType(mount({ name: 42 }));
});테스트 파일 내에서 발생한 모든 타입 오류는 테스트 오류로 처리되므로, 프로젝트의 타입을 테스트하기 위해 원하는 모든 타입 관련 기법을 사용할 수 있습니다.
가능한 매처 목록은 API 섹션에서 확인할 수 있습니다.
오류 읽기
expectTypeOf API를 사용하는 경우, expect-type 문서의 오류 메시지를 참조하십시오.
타입이 일치하지 않을 때, .toEqualTypeOf 및 .toMatchTypeOf는 특별한 헬퍼 타입을 사용하여 가능한 한 실행 가능한 오류 메시지를 생성합니다. 그러나 이를 이해하는 데는 약간의 미묘한 차이가 있습니다. 어설션이 "연속적으로" 작성되었기 때문에 실패는 "예상된" 타입에 있어야 하며 "실제" 타입에 있어서는 안 됩니다 (expect<Actual>().toEqualTypeOf<Expected>()). 이는 타입 오류가 약간 혼란스러울 수 있음을 의미합니다. 따라서 이 라이브러리는 MismatchInfo 타입을 생성하여 기대하는 바를 명확히 하려고 합니다. 예를 들어:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();이는 {a: 1}이 {a: number} 타입이고 {a: string} 타입이 아니기 때문에 실패할 어설션입니다. 이 경우 오류 메시지는 다음과 같이 나타납니다.
test/test.ts:999:999 - error TS2344: Type '{ a: string; }' does not satisfy the constraint '{ a: \\"Expected: string, Actual: number\\"; }'.
Types of property 'a' are incompatible.
Type 'string' is not assignable to type '\\"Expected: string, Actual: number\\"'.
999 expectTypeOf({a: 1}).toEqualTypeOf<{a: string}>()보고되는 타입 제약 조건은 "예상된" 타입과 "실제" 타입을 모두 지정하는 사람이 읽을 수 있는 메시지임을 유의하십시오. Types of property 'a' are incompatible // Type 'string' is not assignable to type "Expected: string, Actual: number" 문장을 문자 그대로 해석하기보다는 속성 이름('a')과 메시지(Expected: string, Actual: number)를 살펴보십시오. 대부분의 경우 무엇이 잘못되었는지 파악하는 데 도움이 될 것입니다. 극도로 복잡한 타입은 디버깅에 더 많은 노력이 필요할 수 있으며, 일부 실험이 필요할 수 있습니다. 오류 메시지가 실제로 오해의 소지가 있는 경우 이슈를 제기해 주시기 바랍니다.
toBe... 메서드(toBeString, toBeNumber, toBeVoid 등)는 테스트 중인 Actual 타입이 일치하지 않을 때 호출 불가능한 타입으로 확인되어 실패합니다. 예를 들어, expectTypeOf(1).toBeString()과 같은 어설션의 실패는 다음과 같이 표시됩니다.
test/test.ts:999:999 - error TS2349: This expression is not callable.
Type 'ExpectString<number>' has no call signatures.
999 expectTypeOf(1).toBeString()
~~~~~~~~~~This expression is not callable 부분은 크게 도움이 되지 않습니다. 의미 있는 오류는 다음 줄인 Type 'ExpectString<number> has no call signatures입니다. 이는 본질적으로 숫자를 전달했지만 문자열로 단언했음을 의미합니다.
TypeScript가 "throw" 타입에 대한 지원을 추가했다면 이러한 오류 메시지는 크게 개선될 수 있었을 것입니다. 그때까지는 어느 정도 주의 깊게 살펴봐야 할 것입니다.
구체적인 "예상된" 객체 vs 타입 인자
다음과 같은 어설션에 대한 오류 메시지:
expectTypeOf({ a: 1 }).toEqualTypeOf({ a: '' });다음과 같은 어설션보다 덜 유용할 수 있습니다:
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();이는 TypeScript 컴파일러가 .toEqualTypeOf({a: ''}) 스타일의 타입 인자를 추론해야 하며, 이 라이브러리는 이를 일반 Mismatch 타입과 비교하여 실패로만 처리할 수 있기 때문입니다. 따라서 가능한 경우 .toEqualTypeOf 및 toMatchTypeOf에는 구체적인 타입 대신 타입 인자를 사용하는 것이 좋습니다. 두 개의 구체적인 타입을 비교하는 것이 훨씬 편리하다면 typeof를 사용할 수 있습니다:
const one = valueFromFunctionOne({ some: { complex: inputs } });
const two = valueFromFunctionTwo({ some: { other: inputs } });
expectTypeOf(one).toEqualTypeof<typeof two>();expectTypeOf API를 사용하고 오류를 파악하는 것이 어렵다면, 언제든지 더 간단한 assertType API를 사용할 수 있습니다:
const answer = 42;
assertType<number>(answer);
// @ts-expect-error answer는 문자열이 아닙니다.
assertType<string>(answer);TIP
@ts-expect-error 구문을 사용할 때, 오타가 없는지 확인하는 것이 좋습니다. 타입 파일을 test.include 설정 옵션에 포함함으로써 Vitest가 실제로 이 테스트를 _실행_하고 ReferenceError로 실패하도록 할 수 있습니다.
이는 오류를 예상하기 때문에 통과하지만, "answer"라는 단어에 오타가 있어 거짓 양성(false positive) 오류입니다:
// @ts-expect-error answer는 문자열이 아닙니다.
assertType<string>(answr); //타입 검사 실행
타입 검사를 활성화하려면 package.json의 Vitest 명령에 --typecheck 플래그를 추가하면 됩니다:
{
"scripts": {
"test": "vitest --typecheck"
}
}이제 타입 검사를 실행할 수 있습니다:
npm run testyarn testpnpm run testbun testVitest는 설정에 따라 tsc --noEmit 또는 vue-tsc --noEmit를 사용하기 때문에, 파이프라인에서 이러한 스크립트를 제거할 수 있습니다.