<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export var seven = 7;
export var seven = 7;"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">var</span> <span class="pl-s1">seven</span> <span class="pl-c1">=</span> <span class="pl-c1">7</span><span class="pl-kos">;</span>
<span class="pl-k">export</span> <span class="pl-k">var</span> <span class="pl-s1">seven</span> <span class="pl-c1">=</span> <span class="pl-c1">7</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">This is <del>valid</del>_invalid_, and TS doesn't error on it.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export var seven = 7;
export var seven = 8;"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">var</span> <span class="pl-s1">seven</span> <span class="pl-c1">=</span> <span class="pl-c1">7</span><span class="pl-kos">;</span>
<span class="pl-k">export</span> <span class="pl-k">var</span> <span class="pl-s1">seven</span> <span class="pl-c1">=</span> <span class="pl-c1">8</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">This is <em>invalid</em>, and TS doesn't error on it.</p>
<p dir="auto"><a href="http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport" rel="nofollow">The spec:</a></p>
<blockquote>
<ol dir="auto">
<li>For each ExportEntry Record e in module.[[StarExportEntries]], do
<ol dir="auto">
<li>Let importedModule be HostResolveImportedModule(module, e.[[ModuleRequest]]).</li>
<li>ReturnIfAbrupt(importedModule).</li>
<li>Let resolution be importedModule.ResolveExport(exportName, resolveSet, exportStarSet).</li>
<li>ReturnIfAbrupt(resolution).</li>
<li>If resolution is "ambiguous", return "ambiguous".</li>
<li>If resolution is not null, then
<ol dir="auto">
<li>If starResolution is null, let starResolution be resolution.</li>
<li>Else
<ol dir="auto">
<li>Assert: there is more than one * import that includes the requested name.</li>
<li>If resolution.[[module]] and starResolution.[[module]] are not the same Module Record or SameValue(resolution.[[exportName]], starResolution.[[exportName]]) is false, return "ambiguous".</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</blockquote>
<p dir="auto"><del>A module is free to export the same value (as in the same value spec function) multiple times, but exporting different values under the same identifier should be a syntax error.</del> This should also be an error:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export var state = {};
export var state = {};"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">var</span> <span class="pl-s1">state</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">export</span> <span class="pl-k">var</span> <span class="pl-s1">state</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Because unique objects do not pass the <code class="notranslate">SameValue()</code> test. (It is not currently reported as an error.)</p>
<p dir="auto"><del>Given that we don't want to attempt to evaluate RHS expressions to resolve the same value functions, we're pretty much stuck using type information to infer the same thing. Or we could just forbid the re-declaration of exports, given that since you're forced the reexport the exact same value or error, there's no <em>real</em> value in doing so.</del></p>
<p dir="auto">And perhaps <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-module-semantics-static-semantics-early-errors" rel="nofollow">the more relevant part of the spec</a> that I found:</p>
<blockquote>
<p dir="auto">15.2.1.1 Static Semantics: Early Errors<br>
It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.</p>
</blockquote>
<p dir="auto">We do forbid multiple default exports already, but don't check other names if the types match for some reason?</p>
<p dir="auto">Type inference seems to fail when the return-type is a union between a class and a generic type.</p>
<p dir="auto">I was hoping to use this pattern to be able to decorate an object (not a class) with traits/behaviors on a per-instance basis, in a type-safe manner, something along the lines of Scala's <code class="notranslate">with</code> operator.</p>
<p dir="auto">Best explained by example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class Fud {}

interface Decorated {
    foo(): string;
}

function decorate&lt;T&gt;(object: T) : T|Decorated {
    object['foo'] = function () {
        return 'Hello';
    };
    return &lt;T|Decorated&gt; object;
}

var test = decorate(new Fud());

console.log(test.foo()); // ERROR"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">Fud</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>

<span class="pl-k">interface</span> <span class="pl-smi">Decorated</span> <span class="pl-kos">{</span>
    <span class="pl-c1">foo</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-en">decorate</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">object</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> : <span class="pl-smi">T</span><span class="pl-c1">|</span><span class="pl-smi">Decorated</span> <span class="pl-kos">{</span>
    <span class="pl-s1">object</span><span class="pl-kos">[</span><span class="pl-s">'foo'</span><span class="pl-kos">]</span> <span class="pl-c1">=</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-k">return</span> <span class="pl-s">'Hello'</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">T</span><span class="pl-c1">|</span><span class="pl-smi">Decorated</span><span class="pl-kos">&gt;</span> <span class="pl-s1">object</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">var</span> <span class="pl-s1">test</span> <span class="pl-c1">=</span> <span class="pl-en">decorate</span><span class="pl-kos">(</span><span class="pl-k">new</span> <span class="pl-smi">Fud</span><span class="pl-kos">(</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">test</span><span class="pl-kos">.</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-kos">;</span> <span class="pl-c">// ERROR</span></pre></div>
<p dir="auto">So anything that goes through the <code class="notranslate">decorate()</code> function comes out decorated with a new interface, which is made possible using a union between a variable type and some interface.</p>
<p dir="auto">Hovering over the call to <code class="notranslate">decorate()</code>, the return-type is correctly reported as <code class="notranslate">Decorated | Fud</code> - however, when the result is assigned to the <code class="notranslate">test</code> variable, the inferred type is <code class="notranslate">Fud</code>, and the attempt to call <code class="notranslate">test.foo()</code> generates the error "property foo does not exist on type Fud".</p>
<p dir="auto">Am I missing something? Is there some reason this shouldn't work?</p>