<p dir="auto">When namespaces merge, any members exported by one namespace declaration are in scope in all the merged declarations. Ambient external modules like <code class="notranslate">declare module "foo" { }</code> can merge too. It seems natural then that exported declarations are in scope in merged external modules too. But external modules have additional ways of exporting their members, via export specifiers, export default, and <code class="notranslate">export *</code>. Should export specifiers contribute to the shared export scope as well?</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare module 'm' {
     export interface I { }
     interface J { }
     interface K { }
     export { K };
     interface L { }
     export { L as L2 };
     export { P } from 'other';
}
declare module 'm' {
     export function f(): I; // in scope because of export modifier
     export function g(): J; // not in scope (lacks export modifier)
     export function h(): K; // should this be in scope?
     export function h(): L; // should this be in scope?
     export function h(): P; // should this be in scope?
}
declare module 'other' {
     export interface P { }
}"><pre class="notranslate"><span class="pl-k">declare</span> module <span class="pl-s">'m'</span> <span class="pl-kos">{</span>
     <span class="pl-k">export</span> <span class="pl-k">interface</span> <span class="pl-smi">I</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span>
     <span class="pl-k">interface</span> <span class="pl-smi">J</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span>
     <span class="pl-k">interface</span> <span class="pl-smi">K</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span>
     <span class="pl-k">export</span> <span class="pl-kos">{</span> <span class="pl-smi">K</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
     <span class="pl-k">interface</span> <span class="pl-smi">L</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span>
     <span class="pl-k">export</span> <span class="pl-kos">{</span> <span class="pl-smi">L</span> <span class="pl-k">as</span> <span class="pl-smi">L2</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
     <span class="pl-k">export</span> <span class="pl-kos">{</span> <span class="pl-smi">P</span> <span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">'other'</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">declare</span> module <span class="pl-s">'m'</span> <span class="pl-kos">{</span>
     <span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-s1">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">I</span><span class="pl-kos">;</span> <span class="pl-c">// in scope because of export modifier</span>
     <span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-s1">g</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">J</span><span class="pl-kos">;</span> <span class="pl-c">// not in scope (lacks export modifier)</span>
     <span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-s1">h</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">K</span><span class="pl-kos">;</span> <span class="pl-c">// should this be in scope?</span>
     <span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-s1">h</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">L</span><span class="pl-kos">;</span> <span class="pl-c">// should this be in scope?</span>
     <span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-s1">h</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">P</span><span class="pl-kos">;</span> <span class="pl-c">// should this be in scope?</span>
<span class="pl-kos">}</span>
<span class="pl-k">declare</span> module <span class="pl-s">'other'</span> <span class="pl-kos">{</span>
     <span class="pl-k">export</span> <span class="pl-k">interface</span> <span class="pl-smi">P</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Today only J is in scope.</p>
<p dir="auto">The key difference between export modifiers and export specifiers is that when an export modifier is used, the exporting entity is guaranteed to have a corresponding local entity with the same name. This is not true of export specifiers, as they can export stuff that is not declared locally, or they can export using a different name.</p>
<p dir="auto">I can think of 4 options. I've listed them in order from smallest export scope to largest export scope:</p>
<ol dir="auto">
<li>Shared export scopes are not created at all for external modules. This is a pretty harsh breaking change.</li>
<li>Only an export modifier (implicit or explicit) can put the name into a shared export scope, but an export specifier cannot. This is the current behavior. It breaks a nice user intuition that using the export modifier is equivalent to leaving it out and writing an export specifier.</li>
<li>An export specifier that exports a locally declared module member with the same name is also in scope and treated just like an export modifier. This sounds like an oddly specific rule. But it maintains the user intuition that option 2 breaks, and when you think about it, it seems pretty natural I think. This would mean that in the above example, I and K are in scope.</li>
<li>All exported entities in a module are in the shared export scope, no matter how they were exported. This is inconsistent with ES6 export semantics.</li>
</ol>
<p dir="auto">I think 1 and 4 are not viable options. 3 seems ideal, but I could also see a case for 2. How about it?</p>
<p dir="auto">Just a suggestion, but it would be very cool if one could create a TypeScript Library project to contain nothing but TypeScript files, which would compile to a single JavaScript file that could then be linked from other projects. Maybe have a Definitions folder to contain .d.ts files. If the source-map-based debugging could be made to work with this project type, then even better.</p>
<p dir="auto">I'm guessing the project would need the same kind of ordering semantics as F# projects, so that the output was concatenated in the correct order.</p>
<p dir="auto">Since TypeScript's raison d'etre is large-scale applications, it would seem to make sense to support this level of componentization in a Visual Studio solution, right?</p>