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

为何使用`as`关键字映射类型会丢失文档注释?

问题:类型映射中使用as关键字时保留属性文档注释

我从对象提取类型时,希望生成的类型属性保留原对象的JSDoc注释,但使用as关键字进行键过滤后,注释丢失了。以下是具体场景:

示例代码

原对象与类型定义

/** 用于提取类型的源对象 */
const obj = {
  /** 这是id属性的文档注释 */
  id: undefined as string,
  /** 这是num属性的文档注释 */
  num: 22 as number
};

// 通过as关键字过滤值为string类型的属性
type UseAsKeyword<T> = {
  [K in keyof T as Extract<T[K], string> extends never ? never : K]: T[K];
};
// 直接映射所有属性的类型
type NoAsKeyword<T> = { [K in keyof T]: T[K] };

type ObjWithAs = UseAsKeyword<typeof obj>;
type ObjNoAs = NoAsKeyword<typeof obj>;

使用时的注释差异

// hover时不显示原对象中id的注释
const testWithAs: ObjWithAs = { id: "hello" };
// hover时正常显示原对象中id和num的注释
const testNoAs: ObjNoAs = { id: "hello", num: 22 };

tsconfig.json配置

{
  "compilerOptions": {
    "composite": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true,
    "strictNullChecks": false
  }
}

我需要实现:在使用as关键字进行键映射的同时保留属性文档注释;如果无法实现,求可保留注释的键映射替代方案。


解决方案

问题根源

截至TypeScript 5.x版本,使用映射类型的as子句时,TypeScript不会保留原始属性的JSDoc注释。这是因为as子句会生成新的键标识符,而非复用原键的元数据(包括注释)。

可行替代方案:Pick+条件类型过滤

如果需求是过滤符合条件的属性,可以通过Pick类型结合条件类型的方式实现,既能过滤属性又能保留注释:

// 过滤出值类型为string的属性
type FilterStringProperties<T> = Pick<T, {
  [K in keyof T]: T[K] extends string ? K : never
}[keyof T]>;

// 生成的类型保留原属性注释
type ObjFiltered = FilterStringProperties<typeof obj>;

验证效果

// hover时正常显示"这是id属性的文档注释"
const testFiltered: ObjFiltered = { id: "hello" };

原理说明

Pick<T, K>类型直接从原类型T中选取指定键K,不会重新定义属性,因此会完整保留原属性的所有元数据(包括JSDoc注释)。内部的条件类型仅用于计算需要保留的键名列表,不会破坏原属性的结构。

其他场景说明

如果需要复杂的键转换(而非单纯过滤),目前TypeScript原生没有保留注释的解决方案。这种情况下可以:

  1. 尝试使用type-fest等类型工具库的预定义工具类型;
  2. 等待TypeScript后续版本对元数据保留的优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:27:16