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

TypeScript 5.0新装饰器能否做类型检查?如何筛选带指定装饰器的类成员

问题

能否对TypeScript 5.0引入的新装饰器(非旧版装饰器)进行类型检查?目前初步认为不可行,但未找到相关答案。

示例代码如下:
装饰器实现:

function EntityOnly<C, ET>(_target: undefined, context: ClassFieldDecoratorContext<C, ET>) {
  // 在此处将字段注册到上下文元数据中
}

使用该装饰器的User类:

class User {
  id: number = 0;
  username: string = '';
  @EntityOnly
  hashedPassword: any = {};
  @EntityOnly
  IBAN: string = '';
}

已知可以通过以下方式筛选出User类中字符串类型成员的键联合类型:

type IfAny<T, Y, N> = 0 extends (1 & T)? Y : N;
type StringMembers<T> = keyof { [P in keyof T as T[P] extends string? IfAny<T[P], never, P> : never]: any; };

// 类型为 "username" | "IBAN"
let userStringMember: StringMembers<User>;

现提问:如何类似地声明由带有EntityOnly装饰器的成员键组成的联合类型?

解答

TypeScript类型系统本身无法直接感知运行时装饰器的应用——装饰器属于运行时特性,编译阶段的类型检查无法直接获取哪些字段被装饰器标记。但可以通过给装饰后的字段添加类型标记的方式,间接实现筛选目标字段的联合类型。

具体实现步骤

  1. 定义一个仅用于类型区分的独特标记,不影响运行时逻辑:
type EntityFieldMarker<T> = T & { __entityField?: never };
  1. 修改装饰器,让它返回的字段类型带上这个标记(运行时注册元数据的逻辑保持不变):
function EntityOnly<C, ET>(_target: undefined, context: ClassFieldDecoratorContext<C, ET>) {
  // 运行时元数据注册逻辑保留
  return function(this: C, value: ET): EntityFieldMarker<ET> {
    return value as EntityFieldMarker<ET>;
  };
}
  1. 定义工具类型,筛选出带有该标记的字段键:
// 判断字段是否带有EntityFieldMarker类型标记
type IsEntityField<T> = T extends EntityFieldMarker<any>? true : false;

// 生成带有EntityOnly装饰器的成员键联合类型
type EntityMembers<T> = keyof {
  [P in keyof T as IsEntityField<T[P]> extends true? P : never]: any;
};
  1. 测试效果:
class User {
  id: number = 0;
  username: string = '';
  @EntityOnly
  hashedPassword: any = {};
  @EntityOnly
  IBAN: string = '';
}

// 类型自动推导为 "hashedPassword" | "IBAN"
let userEntityMember: EntityMembers<User>;

补充说明

如果不想修改字段的实际类型(避免类型标记影响日常类型使用),可以通过显式泛型参数手动指定装饰的字段,但这种方式缺乏自动化。上面的方案通过类型标记间接关联装饰器,是目前最便捷的自动化实现方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 09:57:23