title: Best way to expose types to consumers when using typescript to create libraries/packages?
body: <p>I've been searching and reading related information on this for a while, but still cannot get my head around this.</p>
  
  <p>When I create a library or package using typescript, I like to set <code>declaration</code> to true so that when ts compiler compiles the source code, it will automatically generate declaration files for me. A typical library or package usually has an entry file and a bunch of files dependent with each other. So the outputs for the build result would look like this:</p>
  
  <pre><code>.
  ├── build
  |   ├── entry.js (or entry.min.js in production)
  |   ├── entry.d.ts (it depends on moduleA)
  |   ├── moduleA.d.ts (it depends on moduleB)
  |   ├── moduleB.d.ts
  |   ├── types.d.ts (contains shared types for every body)
  |   └── util.d.ts (declarations for some random util functions)
  </code></pre>
  
  <p>In <code>package.json</code>, I would just set this:</p>
  
  <pre><code>{
    ...
    "main": "./build/entry.js",
    "types": "./build/entry.d.ts",
    ...
  }
  </code></pre>
  
  <p>The problem is even though <code>entry.js</code> has all the APIs I would like to expose to consumers, <code>entry.d.ts</code> doesn't have all the types I would like to also expose. That's because even though <code>entry.ts</code> has <code>import</code>s from <code>types.ts</code>, the type declarations will not be automatically imported from it. The consumer may want to use some enums I kept in <code>types.ts</code> (thus <code>types.d.ts</code>), which is not in <code>entry.ts</code> (thus <code>entry.d.ts</code>). </p>
  
  <p>One way to use the types is to re-export it in the entry file, something like:</p>
  
  <pre><code>export * from './types';
  // or
  export { EnumA } from './types';
  </code></pre>
  
  <p>Which will allow consumer to do this:</p>
  
  <pre><code>import * as types from 'mylib';
  // or 
  import { EnumA } from 'mylib';
  </code></pre>
  
  <p>This is what I am doing right now, which is more of a manual workflow and there is a good chance that I forget to export some types that a consumer actually needs to use my library. I could just put all of my types/interfaces/enums in one single <code>types.ts</code> file and export everything, but I am not sure if that's the right thing to do.</p>
  
  <p>typescript team is using namespaces to handle this (for example, <a href="https://github.com/Microsoft/TypeScript/blob/master/src/server/types.ts" rel="nofollow noreferrer">server types</a> and <a href="https://github.com/Microsoft/TypeScript/blob/master/src/services/types.ts" rel="nofollow noreferrer">service types</a>), but IMO that is redundant as we are already using ES6 modules. More on that in this post <a href="https://stackoverflow.com/questions/30357634/how-do-i-use-namespaces-with-typescript-external-modules">great cup example for explaining namespaces with modules</a>.</p>
  
  <p>Another workaround of this is to let consumer do </p>
  
  <pre><code>import * as types from 'mylib/build/types'
  </code></pre>
  
  <p>But IMO this is also a bad practise since we are essentially exposed implementation details to consumers, which we may change in the future.</p>
  
  <p>I also want to add to above that if I want to generate library for ES5 codes with commonjs or AMD structure, the <a href="https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require" rel="nofollow noreferrer">typescript offical document</a> says to use <code>export =</code>. Apparently, this will prevent you from using <code>export * from './types'</code> anymore so the above workarounds will not working anymore.</p>
  
  <p>That's where I am right now. Any suggestions? Right now I am leaning towards to use namespace like what typescript teams does, but I would like to hear more thoughts.</p>