The configurations of a TypeScript project can differ for a variety of reasons. But the goals remain clear: we need the editor as well as the compiler to recognize a project and its source files correctly. And tsconfig.json
will do the job.
Introduction to tsconfig.json
A TypeScript project does not have to contain a tsconfig.json
file. However, most editors rely on this file to recognize a TypeScript project with specified configurations and to provide related features.
A tsconfig.json
file accepts three fields: compilerOptions
, files
, and exclude
. For example, a simple tsconfig.json
file could be like the following:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"rootDir": "src",
"outDir": "out"
},
"exclude": [
"out",
"node_modules"
]
}
Or, if you prefer to manage the source files manually, it could be like this:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"rootDir": "src",
"outDir": "out"
},
"files": [
"src/foo.ts",
"src/bar.ts"
]
}
Previously, when we used tsc
, we needed to specify the source files explicitly. Now, with tsconfig.json
, we can directly run tsc
without arguments (or with -w
/--watch
if you want incremental compilation) in a folder that contains tsconfig.json
.
As TypeScript is still evolving, its compiler options keep changing, with new features and updates. An invalid option may break the compilation or editor features for TypeScript. When reading these options, keep in mind that some of them might have been changed.
The following options are useful ones out of the list.
target
specifies the expected version of JavaScript outputs. It could be es5
(ECMAScript 5), es6
(ECMAScript 6/2015), and so on.
Features (especially ECMAScript polyfills) that are available in different compilation targets vary. For example, before TypeScript 2.1, features such as async
/await
were available only when targeting ES6.
The good news is that Node.js 6 with the latest V8 engine has supported most ES6 features. And the latest browsers have also great ES6 support. So if you are developing a Node.js application or a browser application that's not required for backward compatibilities, you can have your configuration target ES6.
Before ES6, JavaScript had no standard module system. Varieties of module loaders are developed for different scenarios, such as commonjs
, amd
, umd
, system
, and so on.
If you are developing a Node.js application or an npm package, commonjs
could be the value of this option. Actually, with the help of modern packaging tools such as webpack and browserify, commonjs could also be a nice choice for browser projects as well.
Enable this option to generate .d.ts
declaration files along with JavaScript outputs. Declaration files could be useful as the type information source of a distributed library/framework; it could also be helpful for splitting a larger project to improve compiling performance and division cooperation.
By enabling this option, TypeScript compiler will emit source maps along with compiled JavaScript.
TypeScript provides built-in support for React JSX (.tsx
) files. By specifying this option with value react
, TypeScript compiler will compile .tsx
files to plain JavaScript files. Or with value preserve
, it will output .jsx
files so you can post-process these files with other JSX compilers.
By default, TypeScript will emit outputs no matter whether type errors are found or not. If this is not what you want, you may set this option to true
.
When compiling a newer ECMAScript feature to a lower target version of JavaScript, TypeScript compiler will sometimes generate helper functions such as __extends
(ES6 to lower versions), and __awaiter
(ES7 to lower versions).
Due to certain reasons, you may want to write your own helper functions, and prevent TypeScript compiler from emitting these helpers.
As TypeScript is a superset of JavaScript, it allows variables and parameters to have no type notation. However, it could help to make sure everything is typed.
By enabling this option, TypeScript compiler will give errors if the type of a variable/parameter is not specified and cannot be inferred by its context.
As decorators, at the time of writing this book, has not yet reached a stable stage of the new ECMAScript standard, you need to enable this option to use decorators.
Runtime type information could sometimes be useful, but TypeScript does not yet support reflection (maybe it never will). Luckily, we get decorator metadata that will help under certain scenarios.
By enabling this option, TypeScript will emit decorators along with a Reflect.metadata()
decorator which contains the type information of the decorated target.
Usually, we do not want compiled files to be in the same folder of source code. By specifying outDir
, you can tell the compiler where you would want the compiled JavaScript files to be.
For small browser projects, we might want to have all the outputs concatenated as a single file. By enabling this option, we can achieve that without extra build tools.
The rootDir
option is to specify the root of the source code. If omitted, the compiler would use the longest common path of source files. This might take seconds to understand.
For example, if we have two source files, src/foo.ts
and src/bar.ts
, and a tsconfig.json
file in the same directory of the src
folder, the TypeScript compiler will use src
as the rootDir
, so when emitting files to the outDir
(let's say out
), they will be out/foo.js
and out/bar.js
.
However, if we add another source file test/test.ts
and compile again, we'll get those outputs located in out/src/foo.js
, out/src/bar.js
, and out/test/test.js
respectively. When calculating the longest common path, declaration files are not involved as they have no output.
Usually, we don't need to specify rootDir
, but it would be safer to have it configured.
Enum is a useful tool provided by TypeScript. When compiled, it's in the form of an Enum.member
expression. Constant enum, on the other hand, emits number literals directly, which means the Enum
object is no longer necessary.
And thus TypeScript, by default, will remove the definitions of constant enums in the compiled JavaScript files.
By enabling this option, you can force the compiler to keep these definitions anyway.
TypeScript 2.1 makes it possible to explicitly declare a type with undefined
or null
as its subtype. And the compiler can now perform more thorough type checking for empty values if this option is enabled.
When emitting declaration files, there could be something you'll need to use internally but without a better way to specify the accessibility. By commenting this code with /** @internal */
(JSDoc annotation), TypeScript compiler then won't emit them to declaration files.
By enabling this option, the compiler will unconditionally emit imports for unresolved files.
Adding source map support
Source maps can help a lot while debugging, no matter for a debugger or for error stack traces from a log.
To have source map support, we need to enable the sourceMap
compiler option in tsconfig.json
. Extra configurations might be necessary to make your debugger work with source maps.
For error stack traces, we can use the help of the source-map-support
package:
$ npm install source-map-support --save
To put it into effect, you can import this package with its register
submodule in your entry file:
import 'source-map-support/register';