<p dir="auto">Right now while using decorators the javascript seems to work, but the types are too strict.</p>
<p dir="auto">As you can see <a href="http://www.typescriptlang.org/Playground#src=declare%20var%20_%3A%20any%3B%0Aexport%20function%20Throttle%28milli%3A%20number%29%20%7B%0A%09interface%20Throttled%20extends%20Function%20%7B%0A%09%09%09now%3A%20Function%0A%09%7D%0A%09return%20function%3CT%20extends%20Throttled%3E%28target%3A%20Object%2C%20propertyKey%3A%20string%2C%20descriptor%3A%20TypedPropertyDescriptor%3CFunction%3E%29%3A%20TypedPropertyDescriptor%3CT%3E%20%7B%0A%09%09%09let%20originalMethod%20%3D%20descriptor.value%3B%0A%09%09%09%2F%2F%20NOTE%3A%20Do%20not%20use%20arrow%20syntax%20here.%20Use%20a%20function%20expression%20in%0A%09%09%09%2F%2F%20order%20to%20use%20the%20correct%20value%20of%20%60this%60%20in%20this%20method%0A%09%09%09descriptor.value%20%3D%20%3Cany%3E_.throttle%28function%28%29%20%7B%0A%09%09%09%09originalMethod.apply%28this%2C%20arguments%29%3B%0A%09%09%09%7D%2C%20milli%29%3B%0A%09%09%09%28%3CThrottled%3Edescriptor.value%29.now%20%3D%20%3Cany%3Efunction%28%29%20%7B%0A%09%09%09%09originalMethod.apply%28this%2C%20arguments%29%3B%0A%09%09%09%7D%3B%0A%09%09%09return%20%3CTypedPropertyDescriptor%3CT%3E%3Edescriptor%3B%0A%09%09%7D%0A%7D%0A%09%0A%0A%0A%09class%20Ctrl%20%7B%0A%0A%09%09constructor%28scope%3A%20any%29%20%7B%20%0A%09%09%20%20%20%20scope.%24watch%28%22foo%22%2C%20this.throttledByClassWatch%29%3B%0A%09%09%09this.throttledByClassWatch.now%28%29%20%2F%2Funrecommended%20now%20call%0A%09%09%7D%0A%09%09%40Throttle%28100000%29%0A%09%09private%20throttledByClassWatch%28%29%20%7B%0A%09%09%7D%0A%09%7D%0A" rel="nofollow">here</a> the following does not compile:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
declare var _: any;
export function Throttle(milli: number) {
    interface Throttled extends Function {
            now: Function
    }
    return function&lt;T extends Throttled&gt;(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor&lt;Function&gt;): TypedPropertyDescriptor&lt;T&gt; {
            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 = &lt;any&gt;_.throttle(function() {
                originalMethod.apply(this, arguments);
            }, milli);
            (&lt;Throttled&gt;descriptor.value).now = &lt;any&gt;function() {
                originalMethod.apply(this, arguments);
            };
            return &lt;TypedPropertyDescriptor&lt;T&gt;&gt;descriptor;
        }
}



    class Ctrl {

        constructor(scope: any) { 
            scope.$watch(&quot;foo&quot;, this.throttledByClassWatch);
            this.throttledByClassWatch.now() //unrecommended now call
        }
        @Throttle(100000)
        private throttledByClassWatch() {
        }
    }
"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">var</span> <span class="pl-s1">_</span>: <span class="pl-smi">any</span><span class="pl-kos">;</span>
<span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-smi">Throttle</span><span class="pl-kos">(</span><span class="pl-s1">milli</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">interface</span> <span class="pl-smi">Throttled</span> <span class="pl-k">extends</span> <span class="pl-smi">Function</span> <span class="pl-kos">{</span>
            <span class="pl-c1">now</span>: <span class="pl-smi">Function</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">return</span> <span class="pl-k">function</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">Throttled</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">target</span>: <span class="pl-smi">Object</span><span class="pl-kos">,</span> <span class="pl-s1">propertyKey</span>: <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-s1">descriptor</span>: <span class="pl-smi">TypedPropertyDescriptor</span><span class="pl-kos">&lt;</span><span class="pl-smi">Function</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span>: <span class="pl-smi">TypedPropertyDescriptor</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
            <span class="pl-k">let</span> <span class="pl-s1">originalMethod</span> <span class="pl-c1">=</span> <span class="pl-s1">descriptor</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">;</span>
            <span class="pl-c">// NOTE: Do not use arrow syntax here. Use a function expression in</span>
            <span class="pl-c">// order to use the correct value of `this` in this method</span>
            <span class="pl-s1">descriptor</span><span class="pl-kos">.</span><span class="pl-c1">value</span> <span class="pl-c1">=</span> <span class="pl-kos">&lt;</span><span class="pl-smi">any</span><span class="pl-kos">&gt;</span><span class="pl-s1">_</span><span class="pl-kos">.</span><span class="pl-en">throttle</span><span class="pl-kos">(</span><span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-s1">originalMethod</span><span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-smi">arguments</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s1">milli</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">(</span><span class="pl-kos">&lt;</span><span class="pl-smi">Throttled</span><span class="pl-kos">&gt;</span><span class="pl-s1">descriptor</span><span class="pl-kos">.</span><span class="pl-c1">value</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">now</span> <span class="pl-c1">=</span> <span class="pl-kos">&lt;</span><span class="pl-smi">any</span><span class="pl-kos">&gt;</span><span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
                <span class="pl-s1">originalMethod</span><span class="pl-kos">.</span><span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">,</span> <span class="pl-smi">arguments</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-kos">}</span><span class="pl-kos">;</span>
            <span class="pl-k">return</span> <span class="pl-kos">&lt;</span><span class="pl-smi">TypedPropertyDescriptor</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span><span class="pl-s1">descriptor</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
<span class="pl-kos">}</span>



    <span class="pl-k">class</span> <span class="pl-smi">Ctrl</span> <span class="pl-kos">{</span>

        <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">scope</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> 
            <span class="pl-s1">scope</span><span class="pl-kos">.</span><span class="pl-en">$watch</span><span class="pl-kos">(</span><span class="pl-s">"foo"</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">throttledByClassWatch</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">throttledByClassWatch</span><span class="pl-kos">.</span><span class="pl-en">now</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c">//unrecommended now call</span>
        <span class="pl-kos">}</span>
        @<span class="pl-smi">Throttle</span><span class="pl-kos">(</span><span class="pl-c1">100000</span><span class="pl-kos">)</span>
        <span class="pl-k">private</span> <span class="pl-en">throttledByClassWatch</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span></pre></div>
<p dir="auto">I might have the types a little wrong but I have tried many other permutations. It seems to be because the expected type is <code class="notranslate">declare type MethodDecorator = &lt;T&gt;(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor&lt;T&gt;) =&gt; TypedPropertyDescriptor&lt;T&gt; | void;</code> and so the input T must match the output T.</p>
<p dir="auto">Ideally the <code class="notranslate">now</code> could also inherit the generic type <code class="notranslate">T</code> so it could be type checked.</p>
<p dir="auto">If we can get this to type check properly, we would have perfect support for boilerplate-free mixins:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare function Blah&lt;T&gt;(target: T): T &amp; {foo: number}

@Blah
class Foo {
    bar() {
        return this.foo; // Property 'foo' does not exist on type 'Foo'
    }
}

new Foo().foo; // Property 'foo' does not exist on type 'Foo'"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-smi">Blah</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">target</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span> <span class="pl-c1">&amp;</span> <span class="pl-kos">{</span><span class="pl-c1">foo</span>: <span class="pl-smi">number</span><span class="pl-kos">}</span>

@<span class="pl-smi">Blah</span>
<span class="pl-k">class</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-en">bar</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">foo</span><span class="pl-kos">;</span> <span class="pl-c">// Property 'foo' does not exist on type 'Foo'</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">new</span> <span class="pl-smi">Foo</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-c1">foo</span><span class="pl-kos">;</span> <span class="pl-c">// Property 'foo' does not exist on type 'Foo'</span></pre></div>