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

TypeScript装饰器相关问题:能否作用于接口及如何让编译器识别其添加的属性类型

TypeScript装饰器相关问题:能否作用于接口及如何让编译器识别其添加的属性类型

当然可以搞定这个问题!要让TypeScript编译器认出装饰器自动添加的_x、_y这类属性,还能正确推断它们的类型,咱们可以从类型扩展和装饰器的类型声明入手,下面给你具体拆解:

  • 第一步:先定义一个泛型类型,描述被装饰后类的属性结构
    这个类型会自动把原类的属性映射成下划线开头的版本,类型和原属性完全一致,相当于提前给TS“打预防针”:这个类会多出这些属性哦!

    type ClassWithUnderscoreProps<T> = T & {
      [K in keyof T as `_${string & K}`]: T[K];
    };
    
  • 第二步:给装饰器补上类型声明和运行时逻辑
    咱们要让装饰器不仅能在代码运行时给类加上属性,还要在编译时把类型信息同步给TS。这里用asserts语法做类型断言,明确告诉TS:经过这个装饰器处理的类,会拥有那些下划线开头的属性:

    // 装饰器的运行时逻辑:给类实例添加下划线属性的访问器
    function addUnderscore(target: any, propertyKey: string | symbol) {
      const underscoreKey = `_${String(propertyKey)}`;
      Object.defineProperty(target, underscoreKey, {
        get() {
          return this[propertyKey];
        },
        set(value) {
          this[propertyKey] = value;
        },
        enumerable: true,
        configurable: true
      });
    }
    
    // 给装饰器加类型声明,让TS识别扩展后的属性
    declare function addUnderscore<T>(
      target: any,
      propertyKey: keyof T
    ): asserts target is ClassWithUnderscoreProps<T>;
    
  • 第三步:在类里用装饰器,TS就能自动识别属性啦
    现在你再用Foo类的实例,TS不仅不会报错,还能正确给出_x、_y的类型提示,赋值时也会做类型检查:

    class Foo {
      @addUnderscore
      x = 1;
    
      @addUnderscore
      y = 2;
    }
    
    const foo = new Foo();
    console.log(foo._x); // TS清楚知道这是number类型,完美识别!
    foo._y = 100; // 赋值也会严格校验类型,超省心
    

如果你的类属性不多,也可以用更直接的接口合并方式:先定义类,再写一个同名接口,手动声明装饰器添加的属性和类型,TS同样能立刻识别:

class Foo {
  @addUnderscore
  x = 1;

  @addUnderscore
  y = 2;
}

// 接口合并,手动告诉TS Foo类还有这些属性
interface Foo {
  _x: number;
  _y: number;
}

简单来说,核心就是通过类型扩展或者接口合并,把装饰器动态添加的属性“同步”给TypeScript编译器,这样它就能准确识别这些属性的存在和类型啦!

备注:内容来源于stack exchange,提问作者user29889977

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:04:27