node.js - 如何在 Typescript 的方法装饰器上创建编译错误?

标签 node.js typescript

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

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

路由应用于静态方法。静态方法可以直接返回一个值,也可以返回一个Promise。 .我想要求这样的 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<any>

最佳答案

您需要添加一些类型来指示您的装饰器工厂返回一个装饰器函数,该函数仅接受具有预期函数签名的属性描述符 (...any[]) => Promise<any> .我继续做了一个通用类型别名 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!

关于node.js - 如何在 Typescript 的方法装饰器上创建编译错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37645970/

相关文章:

typescript - 本地链接 Vue 应用程序和 Vue 库 --> d.ts 问题;

javascript - 在 Promise 的 then() 内设置变量时,变量不会更新

angular - 函数从 pouchDB 获取委托(delegate),插入一些调试数据并返回一个 promise

javascript - 意外 token : io. 监听(服务器)

node.js - 如何将池化与 Node 持久化一起使用?

javascript - Webpack 将变量传递到启动/构建脚本中

javascript - 如何正确配置这个虚拟 Angular 项目

javascript - 有没有办法在 TypeScript 中组合类混合?

javascript - 无法从阿拉伯语翻译成英语 谷歌翻译免费 api

node.js - 403/禁止使用 NodeJS/Express 在 favicon 上显示