【问题标题】:How to Create a Compile Error on Method Decorators in Typescript?如何在 Typescript 中的方法装饰器上创建编译错误?
【发布时间】:2016-06-05 19:34:22
【问题描述】:

我正在开发一个名为 expresskit 的库,它允许您使用装饰器为 express 定义路由/参数/等。我正在进行重构,我想我需要限制路由可以具有的响应类型。例如,这里是现在创建路线的方式-

export default class UserRouter {
  @Route('GET', '/user/:userId')
  public static getUser(@Param('userId') userId: number): any {
    return new User();
  }
}

路由应用于静态方法。静态方法可以直接返回一个值,也可以返回一个Promise。我想要求像这样向前发展的承诺-

export default class UserRouter {
  @Route('GET', '/user/:userId')
  public static async getUser(@Param('userId') userId: number): Promise<User> {
    return Promise.resolve(new User());
  }
}

原因是,这些路由背后的逻辑变得臃肿和复杂,无法处理不同类型的响应。由于大多数路由可能是异步的,我宁愿依靠异步来获得更清晰的核心代码。我的 Route 装饰器函数如下所示-

export default function Route(routeMethod: RouteMethod,
                              path: string) {                       
  return function(object: any, method: string) {
    let config: IRouteConfig = {
      name: 'Route',
      routeMethod: routeMethod,
      path: path
    };

    DecoratorManager.registerMethodDecorator(object, method, config);
  } 
}

我创建了一个通用管理器服务来跟踪装饰器的注册位置。在示例中,我可以获得类以及方法名称。我以后可以像这样引用它-object[method]

在我的装饰器上,我想要求类方法是异步的。但由于我只得到对象和方法名称,我不知道我是否可以这样做。如何要求类方法返回Promise&lt;any&gt;

【问题讨论】:

    标签: node.js typescript


    【解决方案1】:

    您需要添加一些类型来指示您的装饰器工厂返回的装饰器函数只接受具有预期函数签名(...any[]) =&gt; Promise&lt;any&gt; 的属性描述符。我继续为它创建了一个通用类型别名RouteFunction

    type RouteMethod = 'GET' | 'POST'; // or whatever your library supports
    
    // The function types the decorator accepts
    // Note: if needed, you can restrict the argument types as well!
    type RouteFunction<T> = (...args: any[]) => Promise<T>;
    
    // The decorator type that the factory produces
    type RouteDecorator<T> = (
        object: Object,
        method: string,
        desc: TypedPropertyDescriptor<RouteFunction<T>> // <<< Magic!
    ) => TypedPropertyDescriptor<RouteFunction<T>>
    
    // Decorator factory implementation
    function Route<T>(routeMethod: RouteMethod, path: string) : RouteDecorator<T> {                       
      return (object, method, desc) => {
        // Actual route registration goes here
        return desc;
      } 
    }
    

    演示类型检查的示例用法:

    class RouteExample {
    
        @Route('GET', 'test1') // works, return type is a Promise
        test1(): Promise<number> {
            return Promise.resolve(1);
        }
    
        @Route('GET', 'test2') // error, return type not a Promise
        test2(): number {
            return 2;
        }
    
        @Route('GET', 'test3') // error, property is a number rather than a function
        get test3(): Promise<number> {
            return Promise.resolve(3);
        }
    
    }
    

    Try it on the playground!

    【讨论】:

      猜你喜欢
      • 2016-04-27
      • 2019-11-12
      • 1970-01-01
      • 2019-08-31
      • 1970-01-01
      • 2018-06-08
      • 1970-01-01
      • 2016-11-11
      • 2016-03-27
      相关资源
      最近更新 更多