hckr.fyi // thoughts

Multiple tsconfig Files for a Single TypeScript Project

by Michael Szul on

TypeScript is a powerful language for many different reasons, but one the more powerful features revolves around TypeScript being capable of targeting multiple outputs, whether that means different modules for packaging or different ECMAScript versions to match browser compatibility. TypeScript makes setting these configurations easy with the usage of a tsconfig.json file, which describes the project.

Sometimes, however, it might be necessary to have multiple configuration files. Maybe you want one that targets AMD modules and ES5 browser compatibility for web application usages, but you need another one to produce CommonJS modules with an ES6 target for NodeJS development. The people at Microsoft thought of this, and implemented a little known feature for extending tsconfig files for additional use cases.

Recently, I answered a question on StackOverflow dealing with multiple targets:

Bear in mind that you could also create multiple tsconfig files and use the extends feature to create a base tsconfig that covers most of the elements, and then two target tsconfigs that cover the targets.

What follows is a basic configuration where one tsconfig is used as a base for other tsconfigs that can be used as different targets.

Base tsconfig:

    {
            "compilerOptions": {
            "module": "commonjs",
            "moduleResolution": "node",
            "sourceMap": true,
            "emitDecoratorMetadata": true,
            "experimentalDecorators": true,
            "removeComments": false,
            "noImplicitAny": false,
            "types" : []
           },
           "exclude": [
             "node_modules"
           ]
        }
    

ES5 tsconfig:

    {
            "extends": "./base.json"
            "compilerOptions": {
                "target": "es5"
            }
        }
    

ES6 tsconfig:

    {
            "extends": "./base.json"
            "compilerOptions": {
                "target": "es6"
            }
        }
    

In this example, you would run whichever target you needed from the command line: For example, tsc -p ./es6.json, if you were targeting ES6.

Of course, this will give you two separate code bases and not one, but it works well. If you add an outDir property to each tsconfig that extends the base, you can then ensure that each outputs to a different directory, preserving the latest output of each. If you're using a task runner like Grunt or Gulp, or even just publishing your module to npm, and having a postinstall script, you can get both commands to run at the same time--outputting all library versions--in one fell swoop.