news 2026/9/25 6:54:23

TypeDoc 文档校验:validation 选项族与警告转错误机制详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TypeDoc 文档校验:validation 选项族与警告转错误机制详解
  • 开发工具
  • 文档

【免费下载链接】typedoc

Documentation generator for TypeScript projects.

项目地址:https://gitcode.com/gh_mirrors/ty/typedoc
点击查看免费下载

本篇指南围绕 TypeDoc 的文档校验(validation)子系统展开,系统讲解validation选项组中notExported、invalidLink、invalidPath、rewrittenLink、notDocumented、unusedMergeModuleWith六个开关的作用与默认值,以及treatWarningsAsErrors、treatValidationWarningsAsErrors、intentionallyNotExported、requiredToBeDocumented、packagesRequiringDocumentation、intentionallyNotDocumented等配套选项。读完本文,你将能够在 CI 中利用 TypeDoc 自动拦截失效链接、未导出类型引用与缺失注释,并通过精确的豁免配置降低误报,把文档质量门禁真正落到命令行上。

校验选项总览:validation 及其默认值

validation是一个标志位(Flags)类型的选项,控制 TypeDoc 在生成文档时执行哪些校验步骤。它既可以整体启用,也可以按子项开关。

CLI 用法:

$ typedoc --validation.invalidLink $ typedoc --validation

typedoc.json中的完整默认值:

{ "validation": { "notExported": true, "invalidLink": true, "invalidPath": true, "rewrittenLink": true, "notDocumented": false, "unusedMergeModuleWith": true } }

这六个开关的语义如下:

  • notExported(默认true):当文档中引用了某个类型,但该类型并未被导出、因而不会被纳入文档时,产生警告。
  • invalidLink(默认true):对无法解析的@link标签产生警告。
  • invalidPath(默认true):对指向不存在文件的相对路径链接产生警告(因为这样的文件无法被复制到文档输出目录)。
  • rewrittenLink(默认true):对能解析成功、但目标在文档中不具有唯一 URL 的@link标签产生警告。TypeDoc 会把这类链接改写为指向最近的、拥有 URL 的父级符号。
  • notDocumented(默认false):对没有文档注释的反射(reflection)产生警告。该行为还受requiredToBeDocumented选项控制。
  • unusedMergeModuleWith(默认true):对未能解析成功的@mergeModuleWith标签产生警告。如果后续要把生成的 JSON 与其他文档合并,一般应当关闭此项。

从源码结构看,上述默认值在 选项声明文件 中被集中定义,validation声明的defaults对象与文档所列完全一致,其中notDocumented是唯一的默认关闭项,因为“要求所有符号都有注释”对多数项目过于严格,需要显式开启。

校验的触发时机与调用链

validation的多数校验发生在渲染之前,但rewrittenLink是一个例外——它是在 HTML 渲染阶段执行的,因为在渲染开始前链接尚未真正生成。

从源码结构看,整个校验流程的入口是Application类上的validate方法,定义于 application.ts。该方法读取validation标志位,按固定顺序依次调用五个校验函数:

  1. notExported→validateExports(exports.ts)
  2. notDocumented→validateDocumentation(documentation.ts)
  3. invalidLink→validateLinks(links.ts)
  4. unusedMergeModuleWith→validateMergeModuleWith(unusedMergeModuleWith.ts)
  5. invalidPath→validateFilePaths(filePaths.ts)

全部执行完毕后,再触发Application.EVENT_VALIDATE_PROJECT事件,供插件介入扩展。值得注意的是notExported校验中存在一条特殊分支:当入口点策略(entry point strategy)为Merge(即合并多个 JSON)时,该校验会被整体跳过——因为在合并模式下,相关警告已在各个子项目 JSON 生成阶段被发出,再次校验属于重复告警。

而rewrittenLink的实际判定并不在validate方法内,而是在主题渲染链接时执行。在 MarkedPlugin.tsx 中,当某个链接目标解析不到唯一 URL 时,代码会沿反射的父级链向上回溯,直到找到一个拥有 URL 的祖先符号,把链接改写过去;只要this.validation.rewrittenLink为真,就会记录一条“链接指向了被改写目标”的警告。这解释了文档中“rewrittenLink 在渲染阶段进行”的描述。

CLI 退出码:警告如何变成错误

校验产生的是“校验警告”(validation warning)。这些警告是否会让构建失败,取决于下面三个开关。

validate方法在 CLI 主流程中的位置见 cli.ts。流程如下:

  • 先执行app.validate(project);
  • 用“校验前后的 warning 计数差”或“validationWarningCount 非零”来判定是否产生了校验警告;
  • 若存在错误,直接返回ExitCodes.ValidationError;
  • 若产生了校验警告,且treatWarningsAsErrors或treatValidationWarningsAsErrors任一为真,同样返回ExitCodes.ValidationError。

此外,treatWarningsAsErrors还会更早地参与判定:在convert()阶段之前、以及之后(convert()返回 project 之后),都会检查logger.hasWarnings(),一旦为真即提前以ExitCodes.CompileError或ExitCodes.OptionError结束。这意味着treatWarningsAsErrors的作用范围比treatValidationWarningsAsErrors更广——它不仅覆盖校验警告,还覆盖转换过程中的所有警告。

treatWarningsAsErrors

$ typedoc --treatWarningsAsErrors

让 TypeDoc 把任何被报告的警告都当作致命错误,从而阻止文档生成。

treatValidationWarningsAsErrors

$ typedoc --treatValidationWarningsAsErrors

TreatWarningsAsErrors的受限版本,只作用于项目校验阶段产生的警告。需要特别注意:它不能用来关闭针对校验警告的treatWarningsAsErrors——也就是说,如果treatWarningsAsErrors已经打开,它会把校验警告也算作错误,而treatValidationWarningsAsErrors无法反向撤销这一行为。

两个选项都在 选项声明文件 中以布尔类型注册,默认值均为关闭(未显式设true即为false)。

notExported 校验与 intentionallyNotExported 豁免

notExported校验的实现位于 validateExports。它会遍历项目中所有被引用的类型,当满足以下条件时发出警告:

  • 该类型没有对应的反射(!type.reflection);
  • 没有外部 URL(!type.externalUrl);
  • 没有被显式标记为“故意不可解析”;
  • 不在intentionallyNotExported豁免清单中;
  • 该唯一标识尚未被警告过(用于去重,同一类型只告警一次);
  • 该符号 ID 未被移除(symbolIdHasBeenRemoved)。

从源码结构看,有几处值得注意的细节:

  • 第三方符号不告警:若引用类型的package不等于当前项目的packageName,则直接跳过(exports.ts)。也就是说,引用外部依赖里的未导出类型不会触发校验警告。
  • 无声明符号隐式放行:极少数类型(例如globalThis上的undefined,或非同质映射类型上的属性)没有声明信息,无法给出“在哪里未导出”的可靠报错,因此被隐式允许,并记录一条 verbose 调试日志。
  • 豁免清单的精确匹配:intentionallyNotExported支持package/relative/path:Name格式,只有当名称匹配且符号所在文件的packageName/packagePath以指定前缀结尾时才命中(exports.ts)。

intentionallyNotExported

用于列出那些“故意被排除在文档输出之外、不应产生警告”的符号。条目可选地在冒号前指定包名/包内相对文件名,以便只对声明在特定文件中的符号进行豁免。

{ "intentionallyNotExported": [ "InternalClass", "typedoc/src/other.ts:OtherInternal" ] }

InternalClass表示对该名称全局豁免;typedoc/src/other.ts:OtherInternal表示只对声明在typedoc/src/other.ts中的OtherInternal豁免。该选项在 选项声明文件 中以数组类型注册。

一个实用的自检点:如果豁免清单里有某条目始终没有匹配到任何符号,validateExports会在结尾收集getUnused()并输出“无效的 intentionallyNotExported 符号”警告(exports.ts)。这把“豁免配置写错”本身也纳入了校验范围,帮助发现拼写错误。

notDocumented 校验:requiredToBeDocumented 与豁免机制

notDocumented是默认关闭的选项,需要显式开启。其实现位于 validateDocumentation。

符号类型到签名的映射

文档要求“必须被文档化”的类型由requiredToBeDocumented指定。但由于函数、构造函数、访问器本身从不直接携带注释,真正需要注释的是它们内部的签名,因此校验逻辑会做如下转换(documentation.ts):

  • Function/Method→ 展开为CallSignature,并移除原标志;
  • Constructor→ 展开为ConstructorSignature;
  • Accessor→ 展开为GetSignature | SetSignature。

这正是文档示例中注释“Implicitly set if function/method is set”背后的实现原因——你无法“只要求方法有注释、却不要求函数有注释”,因为二者共用同一签名注释存储机制。

特殊豁免与包过滤

validateDocumentation在判断某反射是否缺少注释时,还包含几条规则:

  • 参数内部不检查:若反射位于某个参数(parameter)内部,直接跳过,因为回调参数的值不会被深度文档化(documentation.ts)。
  • 类型别名拥有自己的注释:类型字面量(TypeLiteral)若属于某个类型别名(TypeAlias),则改为检查其父级类型别名;构造签名若在类型别名内部,也按父级类型别名判断注释(documentation.ts)。
  • 签名可被父级“顺带”文档化:若反射是签名且自身无注释,但其父反射有注释,则视为已文档化(对应 issue #2644,documentation.ts)。
  • 按包过滤:若符号所属包不在packagesRequiringDocumentation列表中,则跳过检查(documentation.ts)。

命中豁免(intentionallyNotDocumented)的条目会被记入intentionalUsage集合;校验结束后,未被使用的豁免条目同样会被报告为“无效”警告(documentation.ts),与intentionallyNotExported的自检逻辑一致。

requiredToBeDocumented 的可选值

requiredToBeDocumented指定哪些反射类型必须拥有文档注释,供validation.notDocumented使用。完整可选值列表如下(未要求默认注释的类型以注释形式标出):

{ "requiredToBeDocumented": [ // "Project", // "Module", // "Namespace", "Enum", "EnumMember", "Variable", "Function", "Class", "Interface", // "Constructor", "Property", "Method", // 若设置了 function/method 则隐式设置(意味着无法只要求方法有注释而不要求函数有) // 该方法/函数可能因重载存在多个签名,TypeDoc 把注释数据放在签名上。 // 未来可能改进,因此不建议直接设置此项。 // "CallSignature", // 索引签名 { [k: string]: string } 的“属性” // "IndexSignature", // 由于与 CallSignature 相同的实现细节,等价于 Constructor // "ConstructorSignature", // "Parameter", // 用于对象字面量类型。一般应设置 TypeAlias(对应 `type X =` 创建的类型)。 // 此项主要因实现细节而存在。 // "TypeLiteral", // "TypeParameter", "Accessor", // GetSignature + SetSignature 的简写 // "GetSignature", // "SetSignature", "TypeAlias" // 若某符号从包中以多个名称导出,TypeDoc 会创建引用反射。 // 多数项目不会有这些,它们仅渲染为指向规范名称的链接。 // "Reference", ] }

从源码结构看,requiredToBeDocumented是一个带校验的数组选项:每个取值都会被与ReflectionKind的合法键做比对,非法值会直接抛出错误并列出所有合法取值(选项声明文件)。其默认值来自OptionDefaults.requiredToBeDocumented。

packagesRequiringDocumentation

指定 TypeDoc 预期哪些包必须拥有文档,默认取package.json中的包名。

{ "packagesRequiringDocumentation": ["typedoc", "typedoc-plugin-mdn-links"] }

在validateDocumentation的调用处,若未显式设置packagesRequiringDocumentation,则默认使用项目的packageName(application.ts)。该选项让多包(monorepo)场景下,可以精确限定“哪些包”的未文档化符号需要告警。

intentionallyNotDocumented

用于有选择地忽略未被文档化的字段,供validation.notDocumented使用。其中应包含“当某成员无法或不应被正常文档化时,所打印出的限定名(qualified name)”。

{ "intentionallyNotDocumented": ["Namespace.Class.prop"] }

该值用于精确匹配反射的getFriendlyFullName()(documentation.ts)。因此,最稳妥的填写方式是:先触发一次未文档化警告,把日志里打印出的限定名原样复制进此数组。

invalidLink、invalidPath 与 unusedMergeModuleWith 校验

invalidLink 校验

invalidLink的实现位于 validateLinks。它遍历项目中所有反射,检查:

  • 项目/模块的 readme(reflection.readme);
  • 文档反射(@document)的内容;
  • 每个反射的注释(summary 与所有 block tag 内容)。

被检查的链接标签为@link、@linkcode、@linkplain(links.ts)。当一个内联标签是上述三种之一、且其target为空或仍是一个未解析的ReflectionSymbolId时,即被视为“损坏链接”并报告。

一个贴心的细节:如果失效链接文本以@开头但不含!,TypeDoc 会推断用户本意是链接到“包含@的包名”下的绝对链接,并额外提示“你可能本意是@x!y形式”(links.ts)。注释里还提到@是 TSDoc 组件路径中的未来保留字符(对应 issue #2360)。

invalidPath 校验

invalidPath的实现位于 validateFilePaths。它遍历项目中登记的全部媒体文件路径(project.files.getMediaPaths()),对每一条检查其是否为真实存在的文件(isFile);若不存在,则警告“该相对路径不是文件,将不会被复制到输出目录”。

unusedMergeModuleWith 校验

unusedMergeModuleWith的实现位于 validateMergeModuleWith。它遍历所有模块反射,若模块注释里存在@mergeModuleWith标签但未被成功解析,则报告“未使用的 @mergeModuleWith 标签”;同样地,若项目注释上带有该标签也会被报告。由于该选项默认开启,在多包合并生成 JSON 的场景下,通常需要把它关掉以避免噪音。

实战建议

  • 最小门禁:在 CI 中同时启用--treatValidationWarningsAsErrors,让失效链接(invalidLink)、未导出引用(notExported)、坏路径(invalidPath)成为阻断项,而不必把所有警告都升级为错误。
  • 渐进式注释覆盖:先在本地开启notDocumented与requiredToBeDocumented,观察告警,再逐步把高频符号补上注释,必要时用intentionallyNotDocumented精确豁免,避免“一刀切”。
  • 精确豁免:intentionallyNotExported与intentionallyNotDocumented都自带“未使用条目”自检,写错豁免名会被反向告警,可放心使用来收敛误报。
  • 多包场景:用packagesRequiringDocumentation限定需要注释的包范围,并在合并 JSON 时关闭unusedMergeModuleWith,避免跨包告警与合并噪音。

综上,TypeDoc 的校验子系统以validation标志组为核心、以Application.validate为统一入口,将链接、导出、路径、注释、模块合并五类质量检查编织进生成流水线;配合treatWarningsAsErrors/treatValidationWarningsAsErrors与一组精确豁免选项,可以让“文档必须可解析、可引用、可维护”这一约束真正在 CI 中以退出码的形式落地。

  • 开发工具
  • 文档

【免费下载链接】typedoc

Documentation generator for TypeScript projects.

项目地址:https://gitcode.com/gh_mirrors/ty/typedoc
点击查看免费下载
上一篇:高效构建GTA 5增强菜单:YimMenuV2完整实战指南
下一篇:React Native Keyboard Spacer 项目推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 6:50:33

FT2232H+MPSSE:手把手搭出USB转JTAG调试链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 6:48:09

AMD平台RL训练bitwise一致:RL-Kernel与vime实战解析

如果你问我,在 RL 训练系统里最容易藏雷的地方是哪里,我不会先说分布式采样、内存泄漏或者梯度过大,而是“训练和 rollout 在数值上差了最后几个 bit”。尤其是当训练侧跑在 RL-Kernel 这类自研内核上,环境侧跑在 vime 这类模拟执…

作者头像 李华
网站建设 2026/9/25 6:48:02

Atlas 300V 24G推理卡实战:YOLO模型从PyTorch到OM的完整部署

前阵子帮一个客户做智能质检方案选型,对方手里压着一张 Atlas 300V 24G 卡,开口第一句就问:“这卡到底是运算加速卡吗?能不能直接把 YOLO 跑起来?”我当时就发现,这个疑问其实非常普遍——很多人第一次接触…

作者头像 李华