You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中使用keyof时如何实现DSL全场景符号重命名支持?

解决方案与建议

一、实现全场景重命名支持的方案

1. 替换字符串字面量为类型化键

把${"User name"}这类字符串字面量替换为从Context类型推导的键名,示例代码:

type Context = {
  "User name": string;
  // 其他上下文字段
};

// 限定参数为Context的键类型
function renderVar<K extends keyof Context>(key: K): string {
  return `$\{${key}}`;
}

调用renderVar("User name")时,TypeScript会识别这是Context的键,重命名Context中的字段时,所有引用会自动同步更新。

2. 标签函数绑定模板变量

用标签函数包裹AsciiDoc内容,让TypeScript解析模板中的变量关联到Context:

function asDoc(strings: TemplateStringsArray, ...keys: (keyof Context)[]): string {
  let result = strings[0];
  for (let i = 0; i < keys.length; i++) {
    result += `$\{${keys[i]}}${strings[i + 1]}`;
  }
  return result;
}

// 使用示例
const docContent = asDoc`
User Info: ${"User name"}
`;

这种方式下,模板里的"User name"会被识别为keyof Context的成员,重命名时所有引用都会同步更新。

3. 自定义TypeScript语言服务插件(进阶)

如果上述方案无法满足需求,可以编写TS语言服务插件,识别AsciiDoc模板中的${"xxx"}语法,将其与Context的字段绑定,实现重命名、自动补全的全场景支持。插件可监听TS语言服务的重命名请求,同步更新模板中的对应字符串。

二、最大化TypeScript类型安全的调整方案

  • 强类型上下文约束:将所有模板变量的来源统一到Context类型,禁止使用游离的字符串字面量,所有变量必须是keyof Context的成员。
  • 编译时校验模板变量:封装工具函数,校验AsciiDoc内容中使用的变量是否全部存在于Context中,示例:
    function validateAsDocVariables(content: string, contextKeys: (keyof Context)[]): void {
      const varRegex = /\$\{"([^"]+)"\}/g;
      let match;
      while ((match = varRegex.exec(content)) !== null) {
        const varName = match[1];
        if (!contextKeys.includes(varName as keyof Context)) {
          throw new Error(`Undefined variable: ${varName}`);
        }
      }
    }
    
  • 类型推导的模板生成:使用TS的模板字符串类型,让AsciiDoc模板的变量类型自动继承Context的字段类型,避免类型不匹配。

三、现成DSL工具推荐

  • TSDoc:微软推出的基于TypeScript的文档注释DSL,原生支持类型关联,配合VS Code插件可获得完善的自动补全、重命名支持。
  • Markdoc:Stripe开发的Markdown扩展DSL,支持与TypeScript集成,通过定义Schema约束文档中的变量,具备类型安全和编辑器增强功能。
  • Eta(TypeScript版):轻量模板引擎,可作为DSL用于文档生成,支持类型化变量,配合TS工具链能实现补全和重命名支持。

内容的提问来源于stack exchange,提问作者qwertys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:45:37