- 开发工具
- 文档
【免费下载链接】typedoc
Documentation generator for TypeScript projects.
本篇指南围绕 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 --validationtypedoc.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标志位,按固定顺序依次调用五个校验函数:
notExported→validateExports(exports.ts)notDocumented→validateDocumentation(documentation.ts)invalidLink→validateLinks(links.ts)unusedMergeModuleWith→validateMergeModuleWith(unusedMergeModuleWith.ts)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 --treatValidationWarningsAsErrorsTreatWarningsAsErrors的受限版本,只作用于项目校验阶段产生的警告。需要特别注意:它不能用来关闭针对校验警告的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.
相关推荐
TypeDoc 输入选项详解:entryPoints、entryPointStrategy 与文档范围控制
TypeDoc 输入选项详解:entryPoints、entryPointStrategy 与文档范围控制 本篇指南系统讲解 TypeDoc 中与「输入处理」相
开发工具文档Sanity 结构化内容校验引擎 `@sanity/validation` 完全指南:headless 文档校验、稳定错误码与可取消验证
Sanity 结构化内容校验引擎 @sanity/validation 完全指南:headless 文档校验、稳定错误码与可取消验证 @sanity/valid
CMS前端PHPStan 错误详解:method.missingOverride 与 `[\Override]` 属性强制校验
PHPStan 错误详解:method.missingOverride 与 \Override 属性强制校验 导读 method.missingOverride
开发工具代码质量静态分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考