<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nick Matantsev</title>
    <description>The latest articles on Forem by Nick Matantsev (@unframework).</description>
    <link>https://forem.com/unframework</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F111952%2Febdcd54b-6631-44c3-8c71-5dc1e4b2af5a.jpeg</url>
      <title>Forem: Nick Matantsev</title>
      <link>https://forem.com/unframework</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/unframework"/>
    <language>en</language>
    <item>
      <title>Getting TypeORM to work with Next.js and TypeScript</title>
      <dc:creator>Nick Matantsev</dc:creator>
      <pubDate>Sun, 14 Feb 2021 22:10:15 +0000</pubDate>
      <link>https://forem.com/unframework/getting-typeorm-to-work-with-next-js-and-typescript-1len</link>
      <guid>https://forem.com/unframework/getting-typeorm-to-work-with-next-js-and-typescript-1len</guid>
      <description>&lt;p&gt;I was setting up a new Next.js app (using NextAuth for SSO) and decided to use TypeORM as the database persistence layer. Next.js is great at running TypeScript code without hiccups and TypeORM, while new to me, seemed promising in its minimalism. However, I ran into some non-trivial error messages and bugs trying to get them to play together. And even though most answers were already discovered by other kind folks on the internet, it took me a while to track it all down and combine together into one solution.&lt;/p&gt;

&lt;p&gt;There were three key areas to resolve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;importing TypeScript-formatted entities in Next.js and CLI contexts&lt;/li&gt;
&lt;li&gt;support for TypeORM's decorator syntax + &lt;code&gt;reflect-metadata&lt;/code&gt; in Next.js build pipeline&lt;/li&gt;
&lt;li&gt;preventing hot-module-reload (HMR) class instance confusion during development runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Importing Entities and Connection Config
&lt;/h2&gt;

&lt;p&gt;Normally, TypeORM runs inside a vanilla Node.js environment, which means it cannot consume TypeScript files (such as entity class definitions) without precompilation. For example, there is a common error that happens when the &lt;code&gt;entities&lt;/code&gt; path in TypeORM config refers to TS source files (i.e. &lt;code&gt;src/entity/*.ts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error during schema synchronization:
/project/path/src/entity/User.ts:1
import {
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Next.js and its built-in support for TypeScript I did not expect this problem to happen, but still ended up encountering the above error message.&lt;/p&gt;

&lt;p&gt;The reason is that when TypeORM creates a new connection, it tries to load all the entity class files dynamically based on a path wildcard. That process bypasses the entire Next.js Babel bundling pipeline and falls back on Node.js's built-in module loader. So even though my Next.js server code can import and run entity class TS files just fine, the TypeORM connection initializer lives in a "parallel universe" and naively tries to load them from scratch on its own, which then fails.&lt;/p&gt;

&lt;p&gt;I tried to use &lt;code&gt;ts-node&lt;/code&gt; to compile TS modules on the fly as they get loaded by TypeORM, but then I got a different kind of error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RepositoryNotFoundError: No repository for "User" was found. Looks like this entity is not registered in current "default" connection?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario I ended up having &lt;em&gt;two clones&lt;/em&gt; of each entity class co-existing in memory: one loaded and instantiated by TypeORM + &lt;code&gt;ts-node&lt;/code&gt;, and another one bundled by Next.js pipeline with the rest of server code. Hence the class reference confusion.&lt;/p&gt;

&lt;p&gt;Instead, my approach was to name and import all the entity files explicitly, without an &lt;code&gt;entities&lt;/code&gt; wildcard, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./entity/User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./entity/Account&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then pass an explicit options object to &lt;code&gt;createConnection()&lt;/code&gt; with entity classes directly referenced like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// etc&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Correspondingly, I removed the &lt;code&gt;ormconfig.js&lt;/code&gt; file to avoid any further conflicts.&lt;/p&gt;

&lt;p&gt;I did keep around a separate &lt;code&gt;ormconfig.cli.js&lt;/code&gt; file just for CLI schema sync and migrations. For that to work, I installed &lt;code&gt;ts-node&lt;/code&gt; and added &lt;code&gt;require('ts-node/register')&lt;/code&gt; to the top of the config file so that TS entity definitions can be loaded with no extra fuss. The command-line script looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typeorm --config ormconfig.cli.js schema:sync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Decorator Syntax and &lt;code&gt;reflect-metadata&lt;/code&gt; in Next.js
&lt;/h2&gt;

&lt;p&gt;TypeORM entity class definitions use decorator syntax (e.g. &lt;code&gt;@Entity()&lt;/code&gt;, &lt;code&gt;@Column()&lt;/code&gt;, etc). Also, there has to be a bit of special plumbing to let TypeORM read TypeScript field types such as &lt;code&gt;string&lt;/code&gt; and infer database column types such as &lt;code&gt;varchar&lt;/code&gt;. To make the above work, the TypeORM documentation asks to install a package called &lt;code&gt;reflect-metadata&lt;/code&gt; and also to tweak &lt;code&gt;tsconfig.json&lt;/code&gt; to set &lt;code&gt;emitDecoratorMetadata&lt;/code&gt; and &lt;code&gt;experimentalDecorators&lt;/code&gt; to true.&lt;/p&gt;

&lt;p&gt;However, Next.js does not use TSC (the original TypeScript compiler) and instead relies on Babel's &lt;code&gt;@babel/preset-typescript&lt;/code&gt; package. Because of that, those &lt;code&gt;tsconfig.json&lt;/code&gt; tweaks do not have any effect.&lt;/p&gt;

&lt;p&gt;Instead, I added custom Babel configuration in my Next.js project and included the equivalent options for Babel (see &lt;a href="https://github.com/vercel/next.js/issues/5231#issuecomment-423436252"&gt;this issue about decorator support&lt;/a&gt; and &lt;a href="https://github.com/typeorm/typeorm/issues/2897"&gt;this issue about metadata&lt;/a&gt;). This is what's in the resulting &lt;code&gt;.babelrc&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "presets": [
    [
      "next/babel",
      {
        "class-properties": {
          "loose": true
        }
      }
    ]
  ],
  "plugins": [
    "babel-plugin-transform-typescript-metadata",
    ["@babel/plugin-proposal-decorators", { "legacy": true }]
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extra packages needed to be installed (&lt;code&gt;class-properties&lt;/code&gt; plugin is already included with Next.js): &lt;code&gt;@babel/plugin-proposal-decorators babel-plugin-transform-typescript-metadata @babel/core&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note: you can omit installing &lt;code&gt;reflect-metadata&lt;/code&gt; and &lt;code&gt;babel-plugin-transform-typescript-metadata&lt;/code&gt; if you specify database column types explicitly. Then TypeORM does not have to infer anything from TS types. For some folks that might be preferable from a stability perspective, but at the cost of being more verbose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js HMR and TypeORM Entity Classes
&lt;/h2&gt;

&lt;p&gt;Hot-module-reloading (HMR) throws another monkey-wrench in the works.&lt;/p&gt;

&lt;p&gt;During development, every time you edit your Next.js pages, API routes or other files like entity classes your code ends up being recompiled and reloaded from scratch. Because TypeORM connection manager is not aware of entity class reloads, the connection object quickly gets out of sync and stops being useful.&lt;/p&gt;

&lt;p&gt;E.g. if you have a User entity class, Next.js will load and create a class reference for it - let's call it "User v1". That reference is passed to &lt;code&gt;createConnection&lt;/code&gt; and of course the rest of your code uses it too. Now, once you edit that class file, Next.js will perform a hot reload, and there are now &lt;em&gt;two different class references&lt;/em&gt; living inside runtime memory. One is the original "User v1" and another one is the freshly recompiled "User v2". Your route code is now using the "User v2" class reference, but the connection still has "User v1" in its list of known entities. When you try to e.g. call &lt;code&gt;getRepository(User)&lt;/code&gt; in your code, you will not be passing the same class reference as what TypeORM "knows", so you will get this error again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RepositoryNotFoundError: No repository for "User" was found. Looks like this entity is not registered in current "default" connection?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I saw a few GitHub issues discussing solutions to this (such as &lt;a href="https://github.com/typeorm/typeorm/issues/6241#issuecomment-643690383"&gt;this workaround&lt;/a&gt;). For me, the ultimate answer was to simply get any prior connection and close it before opening a new one.&lt;/p&gt;

&lt;p&gt;Here is a sample code snippet; I put it in a shared central file like &lt;code&gt;src/db.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;connectionReadyPromise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;prepareConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;connectionReadyPromise&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;connectionReadyPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// clean up old connection that references outdated hot-reload classes&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;staleConnection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getConnection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;staleConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// no stale connection to clean up&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// wait for new default connection&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="c1"&gt;// connection options go here&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;})();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;connectionReadyPromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in any function that calls out to TypeORM I add this before performing any database actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await prepareConnection();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may seem a bit onerous to include this in many different spots but there always has to be some sort of wait-until-ready logic for database usage anyway, so this ends up serving that exact purpose.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I hope that the TypeORM docs eventually include Babel-specific config recipes and HMR-friendly "connection refresh" helpers like the above. Also, the dynamic wildcard loader for entities would ideally be pluggable into a bundler pipeline like Next.js's. But for now this combination of settings worked pretty well, and I hope it helps you too!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typeorm</category>
      <category>typescript</category>
      <category>babel</category>
    </item>
    <item>
      <title>TypeScript front-end library compilation for publishing on NPM</title>
      <dc:creator>Nick Matantsev</dc:creator>
      <pubDate>Thu, 26 Nov 2020 16:53:28 +0000</pubDate>
      <link>https://forem.com/unframework/typescript-front-end-library-compilation-for-publishing-on-npm-4e97</link>
      <guid>https://forem.com/unframework/typescript-front-end-library-compilation-for-publishing-on-npm-4e97</guid>
      <description>&lt;p&gt;I have recently been going through the process of packaging and publishing a React UI widget on NPM (&lt;a href="https://www.npmjs.com/package/react-csv-importer"&gt;React CSV Importer&lt;/a&gt;) and wanted to document some of the technical nuances encountered along the way.&lt;/p&gt;

&lt;p&gt;Please note that there are more comprehensive publishing guides out there, such as &lt;a href="https://blog.logrocket.com/the-complete-guide-to-publishing-a-react-package-to-npm/"&gt;this one&lt;/a&gt;; here I want to focus on my experience with a specific aspect of the process: the compilation pipeline for the library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;I am a big fan of TypeScript and use it almost exclusively when writing React front-end apps. There are plenty of tools and patterns that help compile and bundle TypeScript for final deployment to the browser. However, when publishing a &lt;strong&gt;library&lt;/strong&gt;, the build/packaging pipeline has key differences in requirements.&lt;/p&gt;

&lt;p&gt;A published front-end library should provide the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript code included by apps&lt;/li&gt;
&lt;li&gt;TypeScript typings (&lt;code&gt;.d.ts&lt;/code&gt; file for TS apps)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will be installed and referenced by the applications that are consuming our library (referred to as "consuming app" further on). Because those consuming apps have their own build pipelines and language expectations, we have to keep the above output compliant with those expectations. Let's go over them in some detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating JavaScript Code
&lt;/h2&gt;

&lt;p&gt;In the most minimal case, one could simply package up and publish the original TypeScript source code; of course, that excludes a large chunk of consuming apps that cannot use TypeScript for various reasons. This is why we need to compile to JavaScript output before publishing.&lt;/p&gt;

&lt;p&gt;Unlike a regular app, our library's JavaScript code does not have to be bundled and minified into a single file. We can assume that whichever app consumes our library will have its own Webpack/Rollup/etc setup, so we do not need to perform any of that ourselves.&lt;/p&gt;

&lt;p&gt;The simplest build pipeline then is to just run &lt;code&gt;tsc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# output goes into dist folder (cleaned first using rimraf)
rimraf dist &amp;amp;&amp;amp; tsc --outDir dist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To produce the correct "flavour" of JavaScript output, the &lt;code&gt;tsconfig.json&lt;/code&gt; file should include the following in addition to your other settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "target": "ES6", // change to ES5 for much older browsers
    "module": "CommonJS", // change to ES2015 or ESNext for ES module syntax output
    "isolatedModules": true, // may help catch isolation issues
    ... other options ...
  },
  "include": ["src"] // change as needed
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated JavaScript files will get bundled by the consuming app, but they will most likely &lt;em&gt;not&lt;/em&gt; get transpiled for legacy browser compatibility. In other words, what you produce is what will run in the browser or server-side Node process directly (as happens while unit testing or pre-rendering page contents). This is why TypeScript &lt;code&gt;target&lt;/code&gt; should be fairly conservative: e.g. &lt;code&gt;ES6&lt;/code&gt; is probably good enough for most browsers/environments that will run your code at the moment.&lt;/p&gt;

&lt;p&gt;Your TypeScript source files reference each other and third-party module dependencies via &lt;code&gt;import&lt;/code&gt; statements. The &lt;code&gt;module&lt;/code&gt; setting controls what happens to that &lt;code&gt;import&lt;/code&gt; syntax in the resulting JS output. This matters because this will be parsed by the consuming app's Webpack/Rollup/etc bundler, and older versions of bundlers may not recognize the &lt;code&gt;import&lt;/code&gt; keyword. Also, if your code runs in a server-side Node process, the runtime might not support it either. Setting &lt;code&gt;module&lt;/code&gt; to &lt;code&gt;CommonJS&lt;/code&gt; will result in imports being output as &lt;code&gt;require()&lt;/code&gt; calls, which is supported most broadly at the moment.&lt;/p&gt;

&lt;p&gt;Once you produce your output (in the &lt;code&gt;dist&lt;/code&gt; folder in the above example), you might want to refer to the main entry point of your library by adding this to your published &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  ...
  "main": "dist/index.js" // change to your entry .js output
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way when the consuming app imports your library it will be loading the correct file under &lt;code&gt;dist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There might be more complex situations where simple &lt;code&gt;tsc&lt;/code&gt; is not enough to build your library. You may want to set up Babel to perform the transpilation for TypeScript alongside other source formats, e.g. PostCSS for stylesheet theming. Or, you may want to rely on Webpack or Rollup to do the same plus also bundle the files together (which is especially useful for libraries that allow a "raw" option - inclusion via script tags). This post cannot document all these possible advanced use cases, of course, but hopefully this provides a starting point for further research.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating Typings
&lt;/h2&gt;

&lt;p&gt;When your &lt;code&gt;tsc&lt;/code&gt; produces JavaScript output, all the type information (interface declarations, function args and return types) is lost. Hence we want to gather up the typings that were lost and expose them to the consuming app - that is usually referred to as the &lt;code&gt;.d.ts&lt;/code&gt; or "DTS" file.&lt;/p&gt;

&lt;p&gt;The TypeScript compiler has an option to produce typings for every file that it processes, but this is not very useful for us! A lot of internal types should never be exposed to the consuming app, but &lt;code&gt;tsc&lt;/code&gt; has no awareness of what is "internal" versus "external" to the library - so its output will be way too big and include all the unnecessary internal type information.&lt;/p&gt;

&lt;p&gt;For small libraries, the simplest thing to do is to "cheat" a bit. Move externally-visible type declarations in your source code to a central file named something like &lt;code&gt;exports.ts&lt;/code&gt; and import it in your other source files as usual. Then, before publishing, do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp src/exports.ts dist/index.d.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. All you need to do then is add this to your &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  ...
  "types": "dist/index.d.ts"
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The consuming app's TypeScript compiler will now consult your typings file and will be able to perform necessary type safety checks downstream.&lt;/p&gt;

&lt;p&gt;For more advanced use cases, there are helpers such as &lt;a href="https://www.npmjs.com/package/dts-bundle-generator"&gt;dts-bundle-generator&lt;/a&gt;. This type of tool will "intelligently" read through your source code, starting with your library entry-point, and collect exposed type information while discarding anything that is purely internal to the library. There are plenty of new caveats that come with this approach, so that deserves a separate write-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review
&lt;/h2&gt;

&lt;p&gt;This post has described a very basic starter build pipeline for a TypeScript-based front-end NPM module. You will need to figure out a few other things before running "npm publish", but hopefully this provides a reference point for further work. Happy publishing!&lt;/p&gt;

</description>
      <category>react</category>
      <category>library</category>
      <category>typescript</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
