Documentation
【免费下载链接】denoA modern runtime for JavaScript and TypeScript.项目地址: https://gitcode.com/GitHub_Trending/de/deno
This test case checks if@ts-expect-errorcomment works as expected.
// @ts-expect-error const a: string = 42;这段代码块的技术要点在于 `@ts-expect-error` 注释的语义(TypeScript 标准行为,Deno 的本地类型检查遵循同样规则): 1. 注释**必须紧邻错误行上方**(本例中直接位于 `const a: string = 42;` 上一行),其作用是抑制下一行代码的类型错误; 2. 如果下一行实际上没有类型错误,`@ts-expect-error` 本身会触发 `Unused '@ts-expect-error' directive` 报错——因此该注释同时是一个“双向断言”:既声明此处应当出错,又防止错误消失后无人察觉; 3. `const a: string = 42;` 是刻意的类型错误(`number` 不能赋给 `string`),有注释在时检查通过;若删除注释,`deno test --doc` 会在类型检查阶段失败。 这正是该用例的验证目标:doc 测试提取出的代码块在送入类型检查器时,`@ts-expect-error` 注释必须被原样保留并生效。若提取过程丢弃了注释(早期版本曾出现过类似问题),类型检查将直接报 `Type 'number' is not assignable to type 'string'`。 ## 用例的驱动方式:`__test__.jsonc` 规格声明 同目录下的 [__test__.jsonc](https://link.gitcode.com/i/66b4f68c27164e1452586de8122d7bc6) 是该规格测试的执行声明: ```jsonc { "args": "test --doc main.md", "exitCode": 0, "output": "main.out" }含义拆解:
args: "test --doc main.md":等价于在该目录执行deno test --doc main.md。--doc标志告诉 Deno 把目标文件当作文档处理——扫描其中所有ts /typescript 围栏代码块,将每个代码块包装成Deno.test调用,并默认对提取出的本地代码执行类型检查;exitCode: 0:类型检查通过(@ts-expect-error生效)且测试运行时无异常,进程必须以 0 退出。由于代码块本身不含Deno.test调用,--doc会为其自动生成测试包装器,代码块中的语句在测试体中执行;output: "main.out":声明期望的 stdout/stderr 对照基准,供 Deno 的 specs 集成测试框架比对输出。
Deno 的 specs 测试框架(由 tests/specs 下各目录驱动)会在真实构建出的 Deno 二进制上回放这些声明,因此这条用例同时是对--doc抽取器、类型检查器和测试运行器三者的端到端回归保护。
源码级原理:代码块如何被抽成独立可检查模块
Deno 的文档代码提取逻辑位于 cli/util/extract.rs。该模块的核心工作可以概括为三步:
- 扫描围栏代码块:对 Markdown(以及 JSDoc 注释块、HTML 注释等载体)识别出语言标记为
ts/typescript的代码块,并记录起止行号; - 生成带行号定位的虚拟模块:每个代码块得到一个
file:///<原路径>#起-止.ts形式的 specifier(例如file:///main.md#4-11.ts),媒体类型为 TypeScript。这个命名让类型错误信息可以精确指回源文件中的行区间; - 包装为测试:把代码块内容包进
Deno.test("<specifier>", async () => { ... })中,并按需自动导入源文件里的顶层导出(从源码结构看,抽取器会分析块内标识符与源文件导出的对应关系生成import语句,使文档示例可以直接引用同文件的函数而不必手写 import)。
extract.rs内嵌的单元测试本身就包含与本文主题直接相关的回归用例(对应上游 issue #26728,见 extract.rs 第 1819–1845 行):
/** * ```ts * // @ts-expect-error: can only add numbers * add('1', '2'); * ``` */ export function add(first: number, second: number) { return first + second; }期望生成的测试源码为:
import { add } from "file:///main.ts"; Deno.test("file:///main.ts#3-7.ts", async ()=>{ // @ts-expect-error: can only add numbers add('1', '2'); });可以清楚看到:@ts-expect-error注释在“源码 → 生成模块”的转换中被逐字保留,测试包装不会剥离任何行。同一文件中针对 Markdown 输入的测试用例(extract.rs 第 1846–1871 行)则验证了.md文件中代码块被抽取为file:///main.md#4-11.ts的完整路径——这正是markdown_ts_expect_error规格用例所依赖的机制。
姊妹用例:JSDoc 注释中的同名验证
仓库中存在一个结构平行的用例 doc_ts_expect_error/mod.ts,它验证 JSDoc 注释块(而非 Markdown 文件)中的@ts-expect-error:
/** * ```ts * import { add } from "./mod.ts"; * * add(1, 2); * * // @ts-expect-error: can only add numbers * add('1', '2'); * ``` */ export function add(first: number, second: number) { return first + second; }两者共同守住的约束是一致的:无论文档载体是.md还是.ts的 JSDoc,doc 测试抽取后代码块中的注释必须完整保留,且带--doc的运行默认执行类型检查,从而让@ts-expect-error的“此处必须出错”断言在文档语境下同样成立。
如何在本地复现与延伸
在仓库中进入用例目录即可复现(只读参考):
cd tests/specs/test/markdown_ts_expect_error deno test --doc main.md【免费下载链接】denoA modern runtime for JavaScript and TypeScript.项目地址: https://gitcode.com/GitHub_Trending/de/deno
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考