2015-11-13 3 views
1

Прямо сейчас, используя декораторы, работает javascript (принудительная компиляция и метод доступны), но типы слишком строгие.Можете ли вы использовать декораторы TypeScript для добавления свойств к вызову метода?

Как вы можете видеть here следующее не компилируется:

declare var _: any; 
export function Throttle(milli: number) { 
    interface Throttled extends Function { 
      now: Function 
    } 
    return function<T extends Throttled>(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<Function>): TypedPropertyDescriptor<T> { 
      let originalMethod = descriptor.value; 
      // NOTE: Do not use arrow syntax here. Use a function expression in 
      // order to use the correct value of `this` in this method 
      descriptor.value = <any>_.throttle(function() { 
       originalMethod.apply(this, arguments); 
      }, milli); 
      (<Throttled>descriptor.value).now = <any>function() { 
       originalMethod.apply(this, arguments); 
      }; 
      return <TypedPropertyDescriptor<T>>descriptor; 
     } 
} 

class Ctrl { 

    constructor(scope: any) { 
     scope.$watch("foo", this.throttledByClassWatch); 
     this.throttledByClassWatch.now() //unrecommended now call 
    } 
    @Throttle(100000) 
    private throttledByClassWatch() { 
    } 
} 

я мог бы иметь типы немного неправильно, но я перепробовал много других перестановок. Казалось бы, так как ожидаемый тип

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

и поэтому вход T должен соответствовать выходной Т.

В идеале now также может наследовать общий тип T так что это может быть тип проверено.

ответ

1

Система типа TypeScript не может описывать свойства методов.

Что вы могли бы сделать что-то вдоль этих линий:

interface Throttled extends Function { 
    now: Function; 
} 

function Throttle(milli: number) { 
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) { 
     let originalMethod = descriptor.value; 

     descriptor.value = _.throttle(function() { 
      originalMethod.apply(this, arguments); 
     }, milli); 

     (<Throttled>descriptor.value).now = function() { 
      originalMethod.apply(this, arguments); 
     }; 

     return descriptor; 
    }; 
} 

class Ctrl { 
    constructor(scope: any) { 
     this.runNow(this.throttledByClassWatch); 
    } 

    @Throttle(100000) 
    private throttledByClassWatch() { 
    } 

    private runNow(method: Function, ...args: any[]) { 
     (method as Throttled).now.apply(this, args); 
    } 
} 

В основном, имеет многоразовую функцию, которая абстрагирует вызов .now() на дросселирования методов.

+0

Спасибо, я использовал этот подход. Эта проблема также связана с https://github.com/Microsoft/TypeScript/issues/4881 – CodySchaaf