Use typescript … while exporting “.mjs” modules

Typescript offers great safety against data corruption, it verifies every part of the data flow in your app and compares it against the libraries signature.
If anything seems wrong, it asks you to double check at compile time.
Ecmascript modules is probably the convergence of frontend and backend javascript : it is seamless across different environments and no longer requires transpilation. Build once, deploy everywhere.

But the two of them are not yet getting along with each other. You can either get an efficiently typed application or an efficiently exported javascript library, but not both.
Then is there any tip to get them both until typescript gets full ecmascript modules support ?

The answer is ‘maybe’, but you will need the typescript transformer library (ttypescript).
Follow these steps and you will be able to use them :
1. add ttypescript and renamer to your application : `yarn add ttypescript renamer -D` or `npm install ttypescript –save-dev`.
2. in addition to your tsconfig.json, add a new file called `tsconfig.esmodules.json` and write the following :

  “extends”: “./tsconfig.json”,
  “compilerOptions”: {
    “module”: “ESNext”,
    “target”: “ES2020”,
    “rootDir”: “src/main”,
    “outDir”: “dist/esmodules”,
    “plugins”: [
        “transform”: “./add-mjs-extension-transformer.js”,
        “after”: true,

3. Then create a file called “add-mjs-extension-transformer.js” and paste in the content from

4. Go to your package.json, add a script to build your project with ttypescript and add an extra step to automatically rename all the .js files into .mjs files :

  “scripts”: {
    “build”: “rimraf dist out && npm run build:commonjs && npm run build:esm”,
    “build:commonjs”: “tsc”,
    “build:esm”: “ttsc -p tsconfig.esmodules.json && npx renamer -s -f ‘/\\.js$/’ –replace ‘.mjs’ ‘dist/esmodules/**'”

5. From now on, your typescript project will build ecmascript modules with the command npm run build:esm ; the below is how your published mjs files will look like :

import { setTaskMetadata } from “./utilities/function-metadata.mjs”;
import { transformLegacyConfig } from “./utilities/transform-legacy-config.mjs”;
* Class representing gulp registry.
* @class
* @extends UndertakerRegistry
export default class MyRegistry extends UndertakerRegistry {
* Build a `MyRegistry` instance which inherits the `UndertakerRegistry`’s get, set, and tasks functions.
* @param {WebappConfig} config – Webapp config based on the `config.js` schema in the readme
* @param {Tasks} taskOverrides – Dictionary of functions to override registry defined tasks
constructor(config = { bundles: {} }, taskOverrides = {}) {

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.