<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.7.5 / 1.8.0-beta / nightly (1.9.0-dev.20160217)</p>
<p dir="auto"><strong>Code</strong></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// A self-contained demonstration of the problem follows...
switch (true) {
  case true:
    let foo = true;
}

switch (true) {
  case true:
    let foo = false;
}

console.log(foo);
// Static type checking correctly says, &quot;Cannot find name 'foo'&quot;
// but compiler transforms it anyway and does not perform hygiene
// on each foo variable.
// Should be Uncaught ReferenceError: foo is not defined
"><pre class="notranslate"><span class="pl-c">// A self-contained demonstration of the problem follows...</span>
<span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>:
    <span class="pl-k">let</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>:
    <span class="pl-k">let</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-c1">false</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">foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// Static type checking correctly says, "Cannot find name 'foo'"</span>
<span class="pl-c">// but compiler transforms it anyway and does not perform hygiene</span>
<span class="pl-c">// on each foo variable.</span>
<span class="pl-c">// Should be Uncaught ReferenceError: foo is not defined</span></pre></div>
<p dir="auto"><strong>Expected behavior:</strong><br>
Identifier hygiene is performed on each lexically bound <code class="notranslate">let foo</code> to their parent <code class="notranslate">SwitchBlock</code>.</p>
<p dir="auto">Output example of expected:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="switch (true) {
  case true:
    var foo_1 = true;
}

switch (true) {
  case true:
    var foo_2 = false;
}

console.log(foo);
// Uncaught ReferenceError: foo is not defined"><pre class="notranslate"><span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>:
    <span class="pl-k">var</span> <span class="pl-s1">foo_1</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>:
    <span class="pl-k">var</span> <span class="pl-s1">foo_2</span> <span class="pl-c1">=</span> <span class="pl-c1">false</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">foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// Uncaught ReferenceError: foo is not defined</span></pre></div>
<p dir="auto"><strong>Actual behavior:</strong><br>
Static type checker sees issue, but transform does not perform hygiene so no <code class="notranslate">ReferenceError</code> happens and instead <code class="notranslate">console.log(foo) === false</code>.</p>
<p dir="auto">The same problem also applies even if you provide explicit blocks inside each <code class="notranslate">CaseClause|DefaultClause</code>, which is even more unexpected:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="switch (true) {
  case true: {
    let foo = true;
  }
}
switch (true) {
  case true: {
    let foo = false;
  }
}
console.log(foo);
// false but should be Uncaught ReferenceError: foo is not defined"><pre class="notranslate"><span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>: <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>: <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-c1">false</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">foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// false but should be Uncaught ReferenceError: foo is not defined</span></pre></div>
<p dir="auto">One thing to note is that if the variable declaration inside the <code class="notranslate">SwitchBlock</code> shadows, then it <em>will</em> correctly perform hygiene:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="let foo = 'this works correctly';

switch (true) {
  case true:
    let foo = true;
}

switch (true) {
  case true:
    let foo = false;
}
console.log(foo);
// &quot;this works correctly&quot;"><pre class="notranslate"><span class="pl-k">let</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-s">'this works correctly'</span><span class="pl-kos">;</span>

<span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>:
    <span class="pl-k">let</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">switch</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">case</span> <span class="pl-c1">true</span>:
    <span class="pl-k">let</span> <span class="pl-s1">foo</span> <span class="pl-c1">=</span> <span class="pl-c1">false</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">foo</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c">// "this works correctly"</span></pre></div>
<p dir="auto"><strong>TypeScript Version:</strong><br>
1.8.7</p>
<p dir="auto"><strong>Code</strong></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// A self-contained demonstration of the problem follows...
class A {
  public propA; any = {};
  private propB: number = 1;
}

class B implements A {
  public propA: any;
  private propB: number;  // here
}
applyMixin(A, [B]);"><pre class="notranslate"><span class="pl-c">// A self-contained demonstration of the problem follows...</span>
<span class="pl-k">class</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
  <span class="pl-k">public</span> <span class="pl-c1">propA</span><span class="pl-kos">;</span> <span class="pl-c1">any</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">;</span>
  <span class="pl-k">private</span> <span class="pl-c1">propB</span>: <span class="pl-smi">number</span> <span class="pl-c1">=</span> <span class="pl-c1">1</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">class</span> <span class="pl-smi">B</span> <span class="pl-k">implements</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
  <span class="pl-k">public</span> <span class="pl-c1">propA</span>: <span class="pl-smi">any</span><span class="pl-kos">;</span>
  <span class="pl-k">private</span> <span class="pl-c1">propB</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>  <span class="pl-c">// here</span>
<span class="pl-kos">}</span>
<span class="pl-en">applyMixin</span><span class="pl-kos">(</span><span class="pl-smi">A</span><span class="pl-kos">,</span> <span class="pl-kos">[</span><span class="pl-smi">B</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><br>
Compile success</p>
<p dir="auto"><strong>Actual behavior:</strong><br>
Compile failed.<br>
When <code class="notranslate">private propB: number;</code> exists, <code class="notranslate">tsc</code> failed with:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="error TS2420: Class 'A' incorrectly implements interface 'B'.
  Types have separate declarations of a private property 'propB'.`"><pre class="notranslate"><code class="notranslate">error TS2420: Class 'A' incorrectly implements interface 'B'.
  Types have separate declarations of a private property 'propB'.`
</code></pre></div>
<p dir="auto">When <code class="notranslate">private propB: number;</code> is removed, <code class="notranslate">tsc</code> failed with:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="error TS2420: Class 'A' incorrectly implements interface 'B'.
  Property 'propB' is missing in Type 'A'."><pre class="notranslate"><code class="notranslate">error TS2420: Class 'A' incorrectly implements interface 'B'.
  Property 'propB' is missing in Type 'A'.
</code></pre></div>