<p dir="auto">Related to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="92706579" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/3714" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/3714/hovercard" href="https://github.com/microsoft/TypeScript/issues/3714">#3714</a>.</p>
<p dir="auto">With the changes to emitting modules with the <code class="notranslate">"use strict";</code> prolog, TypeScript is not applying the appropriate level of code checking to catch block scoped function declaration.</p>
<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.8.2+</p>
<p dir="auto"><strong>Code</strong></p>
<p dir="auto"><a href="http://www.typescriptlang.org/Playground#src=export%20function%20foo%28%29%20%7B%0A%09return%20'foo'%3B%0A%7D%0A%0Aif%20%28true%29%20%7B%0A%09function%20bar%28%29%20%7B%20%2F*%20should%20throw%20error%20that%20functions%20must%20be%20declared%20at%20the%20top%20level%20*%2F%0A%09%09return%20'bar'%3B%0A%09%7D%0A%7D%0A" rel="nofollow">Playground Link</a></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export function foo() {
    return 'foo';
}

if (true) {
    function bar() { /* should throw error that functions must be declared at the top level */
        return 'bar';
    }
}"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-en">foo</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-s">'foo'</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">true</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">function</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-c">/* should throw error that functions must be declared at the top level */</span>
        <span class="pl-k">return</span> <span class="pl-s">'bar'</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>Expected behavior:</strong></p>
<p dir="auto">Error at block level function declaration.</p>
<p dir="auto"><strong>Actual behavior:</strong></p>
<p dir="auto">No error and an invalid emit.</p>
<p dir="auto">From the kangax compatibility table (<a href="http://kangax.github.io/compat-table/es6/#block-level_function_declaration" rel="nofollow">related test</a>):</p>
<blockquote>
<p dir="auto"><a href="http://kangax.github.io/compat-table/es6/index.html#block-level-function-note" rel="nofollow">14</a> Note that prior to ES6, it was <a href="http://wiki.ecmascript.org/doku.php?id=conventions:no_non_standard_strict_decls" rel="nofollow">recommended</a> that ES5 implementations forbid block-level declarations in strict mode.</p>
</blockquote>
<p dir="auto">In ES6, block-level function declarations have block scoping in strict mode. Currently the following is a compiler error in TypeScript:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&quot;use strict&quot;;
function f() { // error TS2393: Duplicate function implementation.
  return 1;
}

{
  function f() { // error TS2393: Duplicate function implementation.
    return 2;
  }
  console.log(f() === 2);
}

console.log(f() === 1);"><pre class="notranslate"><span class="pl-s">"use strict"</span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-c">// error TS2393: Duplicate function implementation.</span>
  <span class="pl-k">return</span> <span class="pl-c1">1</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-kos">{</span>
  <span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> <span class="pl-c">// error TS2393: Duplicate function implementation.</span>
    <span class="pl-k">return</span> <span class="pl-c1">2</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-en">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-c1">2</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-en">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">We should consider the following changes:</p>
<ol dir="auto">
<li>Allow the above in ES6 when in strict mode, with the function declaration <code class="notranslate">f</code> being block-scoped with respect to name resolution.</li>
<li>For ES5 strict-mode, allow the above with the following emit:</li>
</ol>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&quot;use strict&quot;;
function f() {
  return 1;
}

{
  function f_1() {
    return 2;
  }
  console.log(f_1() === 2);
}

console.log(f() === 1);"><pre class="notranslate"><span class="pl-s">"use strict"</span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-en">f</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-c1">1</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-kos">{</span>
  <span class="pl-k">function</span> <span class="pl-en">f_1</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-c1">2</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-en">f_1</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-c1">2</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-en">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">===</span> <span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>