I’m a big fan of TypeScript. Each new project I prefer to write on TS rather than native JavaScript. In this article, I will not discuss the reasons for choosing TypeScript or its advantages and disadvantages. I’d like this article to be a guide for those who want to learn how to set up , to sort out its numerous flags and learn some useful tricks. tsconfig So, in this article I want to provide a revised and streamlined documentation summary, which I believe will be useful to those who are standing at the begging of their path to TypeScript or for those who didn't find time or energy to sort out the details and want to fill this gap. When you’re opening official reference you’ll see a full list of settings divided into groups. However, it doesn't allow you to understand what you should start with and which of these options are required and what can be skipped (for some time). Plus, some options are grouped by technical meaning, not logical. For example, some verification flags could be found in group, some in and others in group. It’s not always easy to understand. tsconfig Strict Checks Linter Checks Advanced All the options, just like the article itself, I divided into two groups – basic and “checks”. In the first part we'll talk about basic settings and in the second – different checks, i.e. tuning compiler strictness. Tsconfig structure Let’s have a look at the structure and some features of the config. has 2 parts. Some options must be specified in and some of them in tsconfig.json root compilerOptions supports comments. Such IDE like WebStorm or Visual Studio understand this and do not highlight comments as a syntax error tsconfig.json supports inheritance. Options can be divided according to some principle, described in different files and merged with the special directive tsconfig.json Here is a blank of : tsconfig.json { // extends you to enrich options with other options from the specified file // we'll return to tsconfig-checks.json file in the next article : , // project-specific options are based in config root : { // all compiler related setting will be placed here } } "extends" "./tsconfig-checks.json" "compilerOptions" options are: , , , , , . Of these, we will consider the first 4. Other options are based in . root extends files include exclude references typeAcquisition compilerOptions Sometimes some options like and can be placed in section. These options are not official and can be used by IDE for its needs. compileOnSave ts-node root Root section extends Type: string | false, default: false. Specifies the path to the file from which to inherit options. For the most part it serves as an organizing tool. Options can be divided according to some logic so that they don’t mix. For example, move config strict settings to separate file the way it’s shown in the config draft. However, given the support of comments in this can be done much easier. tsconfig.json { : { // basic settings block // strict settings block } } "compilerOptions" Let’s have a look at another use-case where comments can’t be a solution. If we need to create production and development configs. This is how version can look: tsconfig-dev.json { : , : { // redefining setting needed for dev env only : , : } } "extends" "./tsconfig.json" "compilerOptions" "sourceMap" true "watch" true In general, I recommend using . But don't break setting too much. This can become confusing. Due to the fact that multiple inheritance is not supported. extends In case of using this option to see the final merged config version use command tsc --showConfig . files Type: string[] | false, default: false, related to include . You can specify a list of specific files for compilation using this option. { : {}, : [ , ] } "compilerOptions" "files" "core.ts" "app.ts" This option will be useful for only small projects with several files. include Type string[], default: depends on files , related to exclude . If option is not set up TypeScript will use this directive to search for files to compile. If is not declared too then its value will be set up as by default. This means that the search for files will be carried out in all folders and their subfolders. This behavior is not optimal, so for performance reasons it’s best to always specify paths. There can be paths to specific files or path patterns. files include ["**/*"] { : {}, : [ , ] } "compilerOptions" "include" "src/**/*" "tests/**/*" If patterns don’t include specific extensions TypeScript will look for , and files. And if flag is enabled - then and files also. .ts .tsx .d.ts allowJs .js .jsx These formats are doing the same src , ./src , src/**/* . I prefer ./src . Technically using include and exclude options TypeScript will create a list of all matched files and place it to files . You can check it by running tsc --showConfig command. exclude Type: string[], default: ["node_modules", "bower_components", "jspm_packages"]. This directive can be used to exclude unnecessary paths of files that was added by directive. By default, the option is set to the paths of the , and package managers, since the modules are already built in them. Besides TypeScript will ignore this folder from option if it was added. This is the folder where the collected built artifacts are placed. It is logical for them to be excluded. To add your values to this option it’s necessary to restore the defaults. Because user’s values are not merging with default values. In other words, you need to manually specify the root of your package manager modules. include npm bower jspm outDir { : {}, : [ , ] } "compilerOptions" "exclude" "node_modules" "./src/**/*.spec.ts" exclude option can’t exclude files added by using files option. exclude option can’t exclude files that imported in other files which are not excluded. compilerOptions section target Type: string, default: ES3 , affects options lib , module . The version of ECMAScript standard in which code will be compiled. Has a lot of choices: , , (same as ), , , , , , . For backend apps/packages is okay if you’re using only modern versions of and , to support the older versions. is supported by at the moment. So, the situation for frontend apps is the same. ES3 ES5 ES6 ES2015 ES2016 ES2017 ES2018 ES2019 ES2020 ESNext ES6 Node.js ES5 ES6 97.29% browsers module Type: string, default: depends on target , affects the option moduleResolution . A modular system that your compiled application will use. You can choose: , , , , , , , or . For backend apps/packages or is suitable depending on version you want to support. For frontend apps is also suitable. And for support of older browsers and isomorphic applications, is definitely worth choosing. None CommonJS AMD System UMD ES6 ES2015 ES2020 ESNext ES6 CommonJS Node.js ES6 UMD If your situation is not so easy or you want to know all the intricacies of modular systems, then you need to learn the . full documentation moduleResolution Type: string, default: depends on module . A strategy will be used for modules import. Includes only two options: and . But won't be using in 99% of cases cause it’s legacy. However, I specifically mentioned this flag as it changes depending on the previous flag. Changing value of option mode can be switched to and the console will start to display error messages on the lines with imports. node classic classic module moduleResolution classic To avoid this situation, I recommend that you always explicitly specify the node value for this flag. lib Type: string[], default: depends on target . TypeScript includes typings ( ) to support the corresponding specifications depending on which is set in the config. For example, if your is set up to TypeScript will include support of and other options that are in this standard. But when is set up to method can’t be used because it’s not available in this JavaScript version. Polyfills can be added. However, in order for TypeScript to understand that this functionality can now be used, it is necessary to include the related typings in the section. Also, you can connect the entire standard or its part (only , etc. methods). *.d.ts-files target target ES6 array.find target ES5 find lib ES2015 ES2015.Core find findIndex Sure it’s better to include typings only for the functionality for which polyfills were previously installed. For --target ES5 will be lined up: DOM, ES5, ScriptHost For --target ES6: DOM, ES6, DOM.Iterable, ScriptHost The defaults are reset at the time you’re adding anything to lib . It’s necessary to manually add what you need, for example DOM : { : { : , : [ , ] } } "compilerOptions" "target" "ES5" "lib" "DOM" "ES2015.Core" outDir Type: string, default: equals a root directory. The final folder where the collected artifacts will be placed. There are: , , and files. If no value was set for this option, then all the above files will be copying the structure of the source files at the root of your project. In this case it’ll create difficulties with deleting previous builds and describing files. As a result, the code base will look like a dump. My advice is to put all artifacts in one folder which may be easily deleted or ignored by the version control system. .js .d.ts .js.map .gitignore If you leave option empty: outDir ├── module │ └── core │ └── core ├── index └── index.ts .js .ts .js If you specify : outDir ├── dist │ └── │ | └── core.js │ └── index.js ├── │ └── core.ts └── index.ts module module outFile Type: string, default: none. According to the description this option allows to unite all files into one. It seems that bundlers like are no longer needed... However, this option works only if , , or value set up for . Much to our regret, the option won't work with or modules. Therefore, you probably won't need to use . Since the option looks so attractive, but does not work as expected, I decided to warn you about this giant pitfall. webpack None System AMD module CommonJS ES6 outFile allowSyntheticDefaultImports Type: boolean, default: depends on module or esModuleInterop . If one of the libraries doesn't have such loaders as or will create it automatically. But files of this library don't know anything about it. This flag allows compiler to write like this: default import ts-loader babel-loader d.ts-files * React ; React ; // instead of this import import as from 'react' // you can use this import from 'react' It's a default option when flag is enabled or === "system". esModuleInterop module esModuleInterop Type: boolean, default: false. By adding a boilerplate to the output code, it allows you to import packages as . CommonJS ES6 Moment ; .log(Moment); .log(Moment); // moment library exporting only like CommonJS // trying to import it as ES6 import from 'moment' // without esModuleInterop flag the result is undefined console // with esModuleInterop flag result is [object Object] console This flag by dependency activates . Together they help to get rid of lots of different imports and write it uniformly across the project. allowSyntheticDefaultImports alwaysStrict Type: boolean, default: depends on strict . Compiler will parse the code in and add to output files. strict mode “use strict” false by default but if flag strict enabled then true. downlevelIteration Type: boolean, default: false. specification added new syntax for iteration: cycle , , . If the project code is compiled to then construction with cycle will be converted to common : ES6 for / of array spread arguments spread ES5 for / of for str = ; ( s of str) { .log(s); } // es6 code const 'Hello!' for const console str = ; ( _i = , str_1 = str; _i < str_1.length; _i++) { s = str_1[_i]; .log(s); } // es5 code without downlevelIteration var "Hello!" for var 0 var console But some symbols like are encoded with two characters. It means that such a transformation will not work as expected in some places. flag generates more verbose and more "correct", but less productive code. This code is huge so I won't take up space on the screen. You can find an example here - - and choose , in settings. emoji downlevelIteration playground target -> es5 downlevelIteration -> true The browser must have an implementation of Symbol.iterator to make this flag work. Otherwise, you'll need to set up polyfill. forceConsistentCasingInFileNames Type: boolean, default: false. Enables case-sensitive mode for files import. Thereby even in case-insensitive file systems trying to make will fail if the file is actually named . It doesn't hurt to play it safe. TypeScript is all about strictness. import FileManager from './FileManager.ts' fileManager.ts section options which are not needed in every project compilerOptions declaration Type: boolean, default: false. By enabling this flag, in addition to JavaScript files, annotation files known as files or typings will be generated for them. d.ts Due to typings it becomes possible to define types for already compiled js files. Other words code is compiling to and types to -files. This can be useful if you're publishing your package to . All developers can use this library whether they're using native JavaScript or TypeScript. js d.ts npm declarationDir Type: string, default: none, related to declaration . Typings are generated next to -files as a default. Using this option you can redirect all files to a separate folder. js d.ts emitDeclarationOnly Type: boolean, default: false, related to declaration . If for some reason you only need the files, then enabling this flag will prevent the generation of files. d.ts js allowJs Type: boolean, default: false. This flag will help you to port your JavaScript project to TypeScript. By enabling flag you'll make TypeScript compiler process not only but also files. There is no need to migrate the whole project before continuing the development. You can do it file by file changing their extensions and adding types to them. And the new functionality can be written directly in TypeScript. allowJs ts js checkJs Type: boolean, default: false, related to allowJs . TypeScript will check for errors not in but in files also. In addition to the built-in typings for JavaScript language constructs, the TS compiler can also use jsDoc to parse files. I prefer not to use this flag but to put the code in order when I add types to it. However, if your project has good jsDoc code coverage, it's worth giving it a try. ts js Since version 4.1 when checkJs is enabled, allowJs flag is automatically enabled. and experimentalDecorators emitDecoratorMetadata Type: boolean, default: false. – is a common OOP pattern. It’s possible to implement it using classical approach by writing wrappers. But using the flags mentioned above, you can enable experimental decorator syntax. This syntax allows you to decorate classes, their methods and properties, access modifiers and function arguments using simple , which is widespread in many programming languages. Decorator “at (@)” syntax The flag just activates the syntax, and provides decorators with additional metadata at runtime, with which you can significantly expand the scope of this feature. experimentalDecorators emitDecoratorMetadata To make emitDecoratorMetadata work you need to add reflect-metadata library. resolveJsonModule Type: boolean, default: false. Flag allows to enable ability to import files. No additional installation is required. *.json config // .json extension must be specified import from './config.json' jsx Type: string, default: none. If the project uses React, you need to enable support. In most cases or option will be enough. It is also possible to leave the untouched with the option or use the custom converters and . jsx react react-native jsx-code preserve react-jsx react-jsxdev Wrapping up the 1st part In this article I wrote about the most important flags and options that can be useful in the vast majority of projects. In the next part I'll talk about compiler strict settings. I will add a link after publishing. Also published on Dev.to