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

如何在普通JavaScript对象的属性上使用TypeScript装饰器?

如何为普通对象属性中的GraphQL解析器应用TypeScript装饰器

问题背景

我们项目里给Apollo GraphQL解析器写了包装函数,用来做认证和前置检查,现在想换成TypeScript装饰器。能找到函数、类/方法上用装饰器的示例:

@decorator
function fn() {}

@clsDecorator
class Cls {
  @methodDecorator
  public myMethod() {}
}

但我们的解析器是从多个模块收集的,定义成普通JS对象的属性,直接给这些属性加装饰器会触发TypeScript-eslint错误(比如Property assignment expected或Declaration expected),而且装饰器根本没生效:

export const ModuleResolvers = {
  Query: {
    // 无效
    @decorator
    queryResolver1(obj, args, context) {}
    // 无效
    @decorator
    queryResolver2: (obj, args, context) => {}
  }
}

解决方案

TypeScript装饰器目前不支持直接用于对象字面量的属性,但可以通过以下几种方式实现类似效果:

1. 手动调用装饰器函数

装饰器本质就是函数,直接把解析器函数作为参数传给装饰器,再赋值给对象属性,这是最直接的方案,完全兼容现有代码结构:

export const ModuleResolvers = {
  Query: {
    queryResolver1: decorator(function(obj, args, context) {
      // 解析器逻辑
    }),
    queryResolver2: decorator((obj, args, context) => {
      // 解析器逻辑
    })
  }
}

2. 用类封装解析器后转成对象

如果想保留装饰器的语法糖,可以把解析器写成类的方法,用装饰器修饰后,再把类实例转换成对象:

class QueryResolvers {
  @decorator
  queryResolver1(obj, args, context) {
    // 解析器逻辑
  }

  @decorator
  queryResolver2(obj, args, context) {
    // 解析器逻辑
  }
}

export const ModuleResolvers = {
  Query: new QueryResolvers()
}

注意:别用箭头函数定义类方法,因为箭头函数是实例属性而非原型方法,装饰器可能无法正常作用。

3. 写工具函数批量处理解析器

如果有大量解析器需要加装饰器,可以写一个工具函数遍历对象属性,批量应用装饰器:

function applyDecoratorsToResolvers<T extends Record<string, Function>>(
  resolvers: T,
  decorator: (fn: Function) => Function
): T {
  const decorated: Partial<T> = {};
  for (const key in resolvers) {
    if (typeof resolvers[key] === 'function') {
      decorated[key] = decorator(resolvers[key]) as T[keyof T];
    }
  }
  return decorated as T;
}

// 使用示例
const rawQueryResolvers = {
  queryResolver1(obj, args, context) {},
  queryResolver2(obj, args, context) {}
};

export const ModuleResolvers = {
  Query: applyDecoratorsToResolvers(rawQueryResolvers, decorator)
};

这种方式能避免重复代码,保持结构整洁。

关键说明

TypeScript的装饰器提案目前主要针对类、类方法、类属性、参数等场景,对象字面量的属性不在官方支持范围内,所以直接用@decorator语法会报错。上述方案里,手动调用装饰器是最贴合现有代码结构、无需大幅重构的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:07:21