
Vitest assertType 完全指南基于 Vite 的类型断言测试实战与原理解析【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitestassertType 是 Vitest 提供的极简类型断言函数用于在*.test-d.ts类型测试文件中校验某个表达式的类型是否与给定泛型一致。本文以 assertType 为核心完整讲解其 API 签名、运行时行为、与 expectTypeOf 的取舍并结合仓库源码与真实测试用例带你掌握如何在 Vitest 中编写、运行与调试类型测试。assertType 是什么面向类型系统的断言函数assertType是 Vitest 暴露的顶层 API 之一其定位非常明确用一行代码、最直观的方式断言这个表达式的类型等于那个泛型。官方文档给出的完整签名如下T(value: T): void调用方式为assertTypeT(value)。例如官方文档中的核心示例import { assertType } from vitest function concat(a: string, b: string): string function concat(a: number, b: number): number function concat(a: string | number, b: string | number): string | number assertTypestring(concat(a, b)) assertTypenumber(concat(1, 2)) // ts-expect-error wrong types assertType(concat(a, 2))在这个示例中concat是一组重载函数两个字符串参数返回string两个数字参数返回number。assertTypestring(concat(a, b))校验字符串拼接的返回值类型为stringassertTypenumber(concat(1, 2))校验数字相加的返回值类型为number。而concat(a, 2)不匹配任何重载签名其返回类型是string | number因此通过ts-expect-error注释声明此处应当报错以此来反向验证类型行为符合预期。关键警示运行时它什么都不做文档开篇即明确警告During runtime this function doesnt do anything. To enable typechecking, dont forget to pass down--typecheckflag.也就是说assertType在运行时是一个空操作它不会抛出异常、不会影响测试通过与否纯粹是写给 TypeScript 编译器看的静态标记。如果不加--typecheck标志这些断言在运行时完全不会被执行。源码级真相一个刻意为空、只为类型而生的函数从源码层面可以完全印证上述行为。在 packages/vitest/src/typecheck/assertType.ts 中assertType的实现极其简洁export interface AssertType { T(value: T): void } export const assertType: AssertType function assertType() {}可以看到两点核心事实类型层面AssertType是一个泛型函数类型接收参数value: T返回void。T(value: T): void意味着只要传入值的类型可赋值给T调用便合法否则 TypeScript 会报类型错误。运行层面函数体是空的——function assertType() {}不接受参数也不返回值。这解释了为什么文档说运行时不做任何事。该函数通过 packages/vitest/src/public/index.ts#L129 从公共入口导出export { assertType } from ../typecheck/assertType因此你可以直接从vitest包导入使用。这一设计背后是 Vitest 类型测试的整体架构类型测试文件并不会被真正执行而是由 TypeScript 编译器静态分析。正如 docs/guide/testing-types.md 所说明的Vitest 底层调用tsc或vue-tsc取决于配置并解析其输出把类型错误呈现为测试错误。因此assertType只需要在类型层面发挥作用运行时实现为空是完全合理的。使用前提启用类型检查要让assertType真正生效必须开启 Vitest 的 typecheck 能力。在package.json中给测试命令加上--typecheck标志{ scripts: { test: vitest --typecheck } }之后按常规方式运行测试即可npm/yarn/pnpm/bun 任选npm run testyarn testpnpm run testbun test启用后Vitest 使用tsc --noEmit或vue-tsc --noEmit取决于配置进行类型检查因此你甚至可以从 CI 流水线中移除原本单独执行的tsc --noEmit脚本。类型测试文件如何被识别默认情况下所有*.test-d.ts文件都会被当作类型测试文件处理。该约定由typecheck.include配置控制其默认值为[**/*.{test,spec}-d.?(c|m)[jt]s?(x)]也就是说foo.test-d.ts、foo.spec-d.ts、foo.test-d.cts、foo.test-d.mts等命名都会被识别。你可以通过 docs/config/typecheck.md 中的typecheck.include/typecheck.exclude自定义匹配范围。typecheck 相关配置项速查以下是与assertType配套使用的核心配置完整说明见 docs/config/typecheck.md配置项类型默认值说明typecheck.enabledbooleanfalse开启类型检查CLI 对应--typechecktypecheck.onlybooleanfalse仅运行类型测试CLI 下会自动开启 typechecktypecheck.checkertsc \| vue-tsc \| stringtsc使用的类型检查工具也可传自定义二进制typecheck.includestring[][**/*.{test,spec}-d.?(c\|m)[jt]s?(x)]视为类型测试文件的 glob 模式typecheck.excludestring[][**/node_modules/**, **/dist/**, ...]排除的类型测试文件typecheck.ignoreSourceErrorsbooleanfalse忽略测试文件之外的源码错误typecheck.tsconfigstring最近的 tsconfig.json自定义 tsconfig 路径typecheck.spawnTimeoutnumber10_000启动类型检查器的超时时间毫秒需要说明的依赖前提使用tsc需要安装typescript包使用vue-tsc需要安装vue-tsc包typecheck.checker也支持传入自定义二进制路径前提是其输出格式与tsc --noEmit --pretty false一致。与 expectTypeOf 的对比何时选择 assertTypeVitest 提供两套类型断言 APIassertType与expectTypeOf后者详见 docs/api/expect-typeof.md。assertType官方定位是expectTypeOf的更简单替代方案——当只需要校验参数类型等于给定泛型时它比expectTypeOf的链式写法更直接。两者的核心差异维度assertTypeexpectTypeOfAPI 风格单函数调用assertTypeT(value)链式调用如expectTypeOf(x).toBeString()表达能力仅类型相等校验丰富的匹配器toEqualTypeOf、toExtend、toBeXxx、.not等适用场景快速校验一个表达式的类型需要精细校验对象结构、联合类型、可扩展性等复杂场景错误信息依赖编译器原生报错 ts-expect-error通过特殊 helper 类型生成可读的Expected: X, Actual: Y信息例如使用expectTypeOf写出的断言可能长这样摘自 docs/guide/testing-types.md 的示例import { assertType, expectTypeOf } from vitest import { mount } from ./mount.js test(my types work properly, () { expectTypeOf(mount).toBeFunction() expectTypeOf(mount).parameter(0).toExtend{ name: string }() // ts-expect-error name is a string assertType(mount({ name: 42 })) })而如果只是判断返回值类型是否为某类型assertType显然更简洁const answer 42 assertTypenumber(answer) // ts-expect-error answer is not a string assertTypestring(answer)docs/guide/testing-types.md也明确指出如果你觉得expectTypeOf的 API 和错误信息难以驾驭随时可以退回到更简单的assertType。ts-expect-error 的正确用法与防呆技巧由于assertType在类型正确时不产生任何运行时效果反向断言必须借助 TypeScript 的ts-expect-error注释当下一行确实存在类型错误时该注释被消费测试通过若下一行没有错误注释本身会报未使用的 ts-expect-error错误从而暴露问题。值得警惕的是拼写错误造成的假阳性。官方文档给出的反面示例// ts-expect-error answer is not a string assertTypestring(answr)这里answr拼错了——它压根不存在因此ts-expect-error同样被满足但测试根本没有校验任何真实类型属于误报通过。官方建议的防呆手段是将类型测试文件也加入test.include见 docs/config/include.md让 Vitest真正运行这些文件。此时拼写错误会触发ReferenceError导致运行失败从而避免假阳性。注意这仅用于开发期自查正常运行 typecheck 时无需如此配置。仓库中的真实应用用 assertType 守护配置类型assertType并非纸上谈兵——Vitest 自身的测试套件就在大量使用它来守护核心配置类型。以 test/coverage-test/test/configuration-options.test-d.ts 为例该文件用几十条assertType断言来校验 coverage 配置的类型定义例如assertTypeCoverage({ provider: v8 }) assertTypeCoverage({ provider: istanbul }) assertTypeCoverage({ reporter: html }) assertTypeCoverage({ reporter: lcov }) assertTypeCoverage({ reporter: [html, json, custom-reporter] })这类测试的价值在于任何人在修改Coverage类型定义如调整provider联合类型、reporter字符串字面量时如果破坏了合法配置的可用性类型测试会立刻报警反之如果有人误将非法值如provider: unknown-provider写成合法类型也会被ts-expect-error机制拦截。这正是用类型测试守护类型定义的最佳实践样板。另外仓库提供了完整的可运行示例 examples/typecheck其中 examples/typecheck/test/type.test-d.ts 展示了expectTypeOf(1).toEqualTypeOf(2)等类型断言写法并配以expect(1).toBe(2) // not executed注释直观演示类型测试文件中的运行时断言不会被执行这一关键行为。类型测试的工作机制与注意事项结合 docs/guide/testing-types.md 的说明使用assertType时还需理解以下几点文件只被静态分析不会运行类型测试文件不会被真正执行。这意味着如果你在类型测试里使用动态测试名、test.each或test.for测试名称不会被求值只会原样显示。测试文件内的任意类型错误都会被视为测试失败你可以使用任何类型技巧来测试项目类型编译器报告的所有错误都会被归类为对应测试的错误。版本行为差异Vitest 2.1 起在 2.1 之前typecheck.include会覆盖include模式导致运行时测试只被类型检查而不会真正运行自 2.1 起若include与typecheck.include重叠类型测试与运行时测试会作为独立条目分别报告。CLI 标志兼容--allowOnly、-t等 CLI 标志同样适用于类型检查。源码错误默认会使套件失败Vitest 默认若在测试文件之外的源码中发现类型错误整个测试套件会失败可通过typecheck.ignoreSourceErrors关闭此行为。总结assertType 的适用画像assertType适合以下场景只需断言某个表达式的类型恰好是某个类型、希望以最少代码维护一组重载签名或 API 返回类型、或作为expectTypeOf链式语法的轻量补充。记住它的三个关键事实签名是T(value: T): void运行时是空函数必须配合--typecheck使用。若需要结构级、可扩展性或更可读的错误信息则升级到 expectTypeOf若想深入了解类型测试的完整配置与运行机制可继续阅读 类型测试指南 与 typecheck 配置文档。【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考