多态装饰器的TypeScript声明

时间:2017-07-25 14:50:52

标签: typescript polymorphism decorator

我正在为react-tracking撰写环境声明。它公开了一个track装饰器,可以在两个类上使用。

摘自文档的简化示例:

import track from 'react-tracking'

@track({ page: 'FooPage' })
export default class FooPage extends React.Component {

  @track({ action: 'click' })
  handleClick = () => {
    // ...
  }
}

在我的环境声明文件中,我希望能够执行以下操作,并让TypeScript选择正确的重载:

declare function track(trackingInfo?: any, options?: any): <T>(component: T) => T
declare function track(trackingInfo?: any, options?: any): any

export default track

虽然这适用于组件类,但对于出现以下错误的方法会失败:

[ts] Unable to resolve signature of method decorator when called as an expression.

查看TS为此装饰器应用程序选择的类型表明它不会回退到应该匹配任何内容的签名,而是返回到组件类1。

enter image description here

是否可以输入多态装饰器?如果是这样,我做错了什么?

更新:这是一个缩小的简化示例。

第一个是单态的,按预期工作:

function trackClass(trackingInfo?: any, options?: any): ClassDecorator {
  return null
}

function trackMethod(trackingInfo?: any, options?: any): MethodDecorator {
  return null
}

@trackClass({})
class Foo {
  @trackMethod({})
  someMethod() {}
}

这第二个例子是多态的,两者都失败了:

function track(trackingInfo?: any, options?: any): ClassDecorator | MethodDecorator {
  return null
}

@track({})
class Bar {
  @track({})
  someMethod() {}
}

1 个答案:

答案 0 :(得分:2)

TypeScript&#39; lib.d.tsClassDecoratorMethodDecorator类型:

declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;

declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;

你可以做以下两件事之一:

  1. 创建一个具有与两者兼容的重载的类型:

    interface TrackDecorator {
        // Class decorator overload
        <TFunction extends Function>(target: TFunction): TFunction;
    
        // Property decorator overload
        <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T>;
    }
    
    export default function track(trackingData?: object): TrackDecorator;
    
  2. 派生一个类型以适当地组合重载。

    interface TrackDecorator extends ClassDecorator, MethodDecorator { }
    export default function track(trackingData?: object): TrackDecorator;
    
  3. 前者允许您更具体,但后者会将您绑定到TypeScript为装饰器设想的任何版本(换句话说,如果规范更改,则暗示react-tracking支持任一版本)。