<p dir="auto">I've noticed an easy area to make a mistake in the language because of this <a href="http://stackoverflow.com/q/30467906/188246" rel="nofollow">SO question</a>. Take this example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class MyClass {
    @SetDefaultValue
    filePath: string;
}

var c = new MyClass();
console.log(c.filePath);

function SetDefaultValue(defaultValue = &quot;Example&quot;) {
    return function (target: Object, propertyKey: string | symbol) {
        target[propertyKey] = defaultValue;
    };
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">MyClass</span> <span class="pl-kos">{</span>
    @<span class="pl-smi">SetDefaultValue</span>
    <span class="pl-c1">filePath</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">var</span> <span class="pl-s1">c</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">MyClass</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">c</span><span class="pl-kos">.</span><span class="pl-c1">filePath</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">function</span> <span class="pl-smi">SetDefaultValue</span><span class="pl-kos">(</span><span class="pl-s1">defaultValue</span> <span class="pl-c1">=</span> <span class="pl-s">"Example"</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-k">function</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-c1">|</span> <span class="pl-smi">symbol</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">target</span><span class="pl-kos">[</span><span class="pl-s1">propertyKey</span><span class="pl-kos">]</span> <span class="pl-c1">=</span> <span class="pl-s1">defaultValue</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">This compiles fine; however, this will output <code class="notranslate">undefined</code>. To fix this, the developer needs to remember to add parentheses:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class MyClass {
    @SetDefaultValue()
    filePath: string;
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">MyClass</span> <span class="pl-kos">{</span>
    @<span class="pl-smi">SetDefaultValue</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
    <span class="pl-c1">filePath</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Now it will output <code class="notranslate">Example</code>.</p>
<p dir="auto">This seems too sneaky to me. I can see this leading to incredibly annoying bugs in applications. Is there any way the compiler could get both ways to work or throw a compile error for one of them?</p>
<p dir="auto">As mentioned in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="60187635" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/2249" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/2249/hovercard?comment_id=104235451&amp;comment_type=issue_comment" href="https://github.com/microsoft/TypeScript/issues/2249#issuecomment-104235451">#2249 (comment)</a>, consider this:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// decorator factory
function F(options?: {optional: boolean}) {
     // returns a property decorator
    return (target , propertyKey): void =&gt; {
        // decorator implementation
    }
}

class C {
    @F()    // OK, used as a factory
    prop1; 

    @F   // No error
    prop2; 
}"><pre class="notranslate"><span class="pl-c">// decorator factory</span>
<span class="pl-k">function</span> <span class="pl-smi">F</span><span class="pl-kos">(</span><span class="pl-s1">options</span>?: <span class="pl-kos">{</span><span class="pl-c1">optional</span>: <span class="pl-smi">boolean</span><span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
     <span class="pl-c">// returns a property decorator</span>
    <span class="pl-k">return</span> <span class="pl-kos">(</span><span class="pl-s1">target</span> <span class="pl-kos">,</span> <span class="pl-s1">propertyKey</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-c">// decorator implementation</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">class</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
    @<span class="pl-smi">F</span><span class="pl-kos">(</span><span class="pl-kos">)</span>    <span class="pl-c">// OK, used as a factory</span>
    <span class="pl-c1">prop1</span><span class="pl-kos">;</span> 

    @<span class="pl-smi">F</span>   <span class="pl-c">// No error</span>
    <span class="pl-c1">prop2</span><span class="pl-kos">;</span> 
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The problem here is that the compiler compares the signature of the decorator factory <code class="notranslate">F</code> against <code class="notranslate">declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) =&gt; void;</code> which ends up to be assignable. I think we need a stronger check here to make sure we catch these issue.</p>