文档文章

创建自定义 generator

从一小块稳定的 Shape IR 开始,逐步扩展到目标格式。

指南15 分钟

自定义 generator 最能说明为什么这个 toolkit 要围绕 Shape IR 来组织,而不是简单做格式到格式的直连适配。

第一阶段不需要一口气覆盖所有高级场景。更合理的目标是先支持一小块稳定的 Shape IR,并且把暂不支持的情况明确报告出来。

适合人群
扩展开发者
难度
高级
最近更新
2026年7月27日
Shape IR
在设计输出规则之前,先理解共享中间表示。
Traversal
看看 traversal 如何帮助 generator pipeline 保持模块化。

先定义一个收敛的契约

generator 接收 Shape IR,然后输出 TypeScript、JSON Schema 或其他目标表示。

它的职责不是复刻 parser 的内部实现,而是把稳定的 IR 节点映射为目标输出规则,并保留足够的 diagnostic 上下文来解释语义损失或暂不支持的情况。

设计第一阶段能力边界

范围明确的第一版更容易测试,也更容易在文档里讲清楚。当前 generator 能力还在扩展,这一点尤其重要。

  • 先选定第一阶段真正要支持的输出面。
  • 列出这一输出面需要处理的 Shape IR 节点类型。
  • 决定哪些不支持情况应该报错、告警或降级。
  • 把格式化逻辑和语义映射逻辑分开。

优先显式降级

只要不支持的情况被明确暴露出来,最初实现完全可以保持很小。静默降级会让后续 round-trip 行为更难信任。

最小 generator 示例

ts
type GeneratorResult = {
  code: string;
  diagnostics: string[];
};

export function emitShape(shape: Shape): GeneratorResult {
  switch (shape.kind) {
    case "string":
      return {code: "string", diagnostics: []};
    case "number":
      return {code: "number", diagnostics: []};
    default:
      return {
        code: "unknown",
        diagnostics: [`Unsupported shape: ${shape.kind}`],
      };
  }
}