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

TypeScript属性装饰器能否访问类的其他属性?

关于TypeScript装饰器检查Point类x和y值关系的问题

咱先直接说结论:你现在给x加的这个属性装饰器,没法直接实现实例化后动态检查x和y大小的需求,得先搞清楚TypeScript装饰器的执行逻辑——属性装饰器是在类定义的阶段就运行了,不是等你new出实例的时候。这时候装饰器能拿到的只是类的原型对象,还有当前属性的描述符,根本碰不到具体实例里的x和y值,哪怕你给x、y设了初始值,那也只是类原型上的默认值,不是每个实例可能被修改后的动态值。

两种场景的解决方案

场景1:只需要检查类定义时的默认初始值

如果你的需求只是确保类里写的x、y默认值符合x≥y的要求,那属性装饰器是可以做到的,直接在装饰器里访问类原型上的y值就行:

function test(myValue: string) {
  function t(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
    // target是Point类的原型对象
    const defaultX = descriptor.value; // 拿到x的默认值6
    const defaultY = (target as any).y; // 拿到原型上的y默认值5
    
    if (defaultX < defaultY) {
      throw new Error(`默认值x(${defaultX})小于y(${defaultY}),不符合要求!`);
    }
  }
  return <any>t;
}

class Point {
  @test('admin')
  x: number = 6;
  y: number = 5;
}

不过要注意,这种写法只会在类定义的时候检查一次默认值,如果你实例化后修改了x或y的值,这个装饰器早就执行完了,根本不会触发检查。

场景2:需要检查实例创建或属性修改时的动态值

如果要在实例创建后,或者每次修改x/y时都检查它们的大小关系,就得换个思路,这里给你两种常用方案:

方案A:用类装饰器在实例创建时检查

类装饰器可以修改类的构造函数,在实例创建完成后做检查:

// 定义类装饰器
function checkXYOnInstance() {
  return function(target: typeof Point) {
    // 保存原来的构造函数
    const originalConstructor = target;
    
    // 重写构造函数
    function NewConstructor(...args: any[]) {
      // 创建实例
      const instance = new originalConstructor(...args);
      // 检查x和y的关系
      if (instance.x < instance.y) {
        throw new Error(`实例的x(${instance.x})小于y(${instance.y}),不符合要求!`);
      }
      return instance;
    }
    
    // 保持原型链不变,避免破坏类的继承关系
    NewConstructor.prototype = originalConstructor.prototype;
    return NewConstructor as typeof Point;
  }
}

@checkXYOnInstance()
class Point {
  x: number = 6;
  y: number = 5;
}

// 实例化时会触发检查
const p1 = new Point(); // 没问题
const p2 = new Point();
p2.y = 7; // 这里不会触发检查,因为构造函数只在创建实例时跑一次

方案B:用访问器(get/set)+装饰器,属性修改时自动检查

如果要每次修改x或y都触发检查,最好把x、y改成访问器属性,然后给setter加装饰器:

// 定义装饰器,给setter添加检查逻辑
function checkXYOnSet() {
  return function(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
    // 保存原来的set方法
    const originalSet = descriptor.set;
    
    // 重写set方法
    descriptor.set = function(value: number) {
      // 先执行原来的set逻辑,设置属性值
      originalSet?.call(this, value);
      // 检查当前实例的x和y
      if (this.x < this.y) {
        throw new Error(`x(${this.x})小于y(${this.y}),不符合要求!`);
      }
    };
    
    return descriptor;
  }
}

class Point {
  private _x: number = 6;
  private _y: number = 5;

  @checkXYOnSet()
  get x() {
    return this._x;
  }

  set x(value: number) {
    this._x = value;
  }

  @checkXYOnSet()
  get y() {
    return this._y;
  }

  set y(value: number) {
    this._y = value;
  }
}

const p = new Point();
p.y = 7; // 修改y时会触发检查,直接抛出错误

这样不管是修改x还是y,只要值不符合要求,都会立即抛出错误,完全满足动态检查的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:33:04