I personally like TypeScirpt, write code with Ts to be more comfortable than Js too much, can greatly improve the efficiency of writing code, reduce the workload of code maintenance. Because I have the foundation of C++ and C#, I can get started with Ts quickly. Although there is no difficulty in using it, but for a long time, did not go to understand the compilation process and configuration of typescirpt, so they can not be considered to really understand it.

If you don’t know much about ts configuration and compilation process, then this article should help you.

The next part requires your environment to have TypeScript installed. Please make sure that TypeScript is installed, otherwise the tsc command will not be recognized.

I.tsc

Ts provides a command line function tsc, which can be used to compile Ts files into Js files.

First create a folder and index.ts file and go to the learnTsConfig folder.

1
2
3
4
5
mkdir learnTsConfig
mkdir learnTsConfig/src
touch learnTsConfig/src/index.ts

cd learnTsConfig

You can enter some Ts code in the index.ts file, e.g.

1
2
3
4
5
6
// src/index.ts
type FuncType = () => void;

const sayHello: FuncType = () => {
    console.log("Hello Ts");
};

Then use the tsc [ts file] command to compile the file.

1
tsc src/index.ts

As you can see, there is an index.js file generated in the same directory as src/index.ts, which is the compiled file, and the contents of the src/index.js file are as follows.

1
2
3
var sayHello = function () {
    console.log("Hello Ts");
};

Specifying the ts file for the tsc command is not applicable to the project, we can’t add all the file paths to be compiled after the tsc command, so we usually use JSON configuration file (tsconfig.json) to configure the tsc compiler. When executing the tsc command, the tsc compiler will first look for the tsconfig.json file in the current directory. If there is no tsconfig.json file in the current directory, it will keep looking up the directory until it finds a tsconfig.json file, the directory where the tsconfig.json file is located is project’s root directory.

If you do not find a tsconfig.json file, the tsc command will not compile any files, but will only output the version number and help information.

The tsconfig.json file is described in detail below.

II. The tsconfig.json file

The tsconfig.json file supports JSON5 content, so you can add comments to the tsconfig.json file, using single quotes instead.

The structure of the tsconfig.json file is as follows.

1
2
3
4
5
6
7
8
9
{
    "files": [],
    // ...
    "compilerOptions": {
        "target": "ES6",
        "module": "CommonJS",
        "outDir": "./dist/development"
    }
}

In the following I will describe the configuration options divided into compiled options (configuration items under the compilerOptions field) and non-compiled options (root-level options outside the compilerOptions field).

First, under the learnTsConfig directory, create a new tsconfig.json file.

1
touch tsconfig.json

Non-compile options

Non-compiled options usually control information about the items (files) to be compiled by the typescript compiler, such as the ts files to be compiled.

  1. files

    files option is used to indicate which files need to be compiled, you can add a set of file paths, support relative paths and absolute paths, relative paths are relative to the project root directory, that is, the directory where the tsconfig.json file is located, it is recommended that you use relative paths, avoid using absolute paths, so that even if the project changes the environment, you do not have to change the configuration.

    Create a new file outerIndex.ts in the root directory, and the directory structure will be as follows

    1
    2
    3
    4
    5
    
    learnTsConfig/
        src/
            index.ts
        outerIndex.ts
        tsconfig.json
    

    Enter the following in the tsconfig.json file.

    1
    2
    3
    4
    5
    6
    7
    
    {
        // files选项用于设置需要编译的文件
        "files": [
            "outerIndex.ts",
            "src/index.ts"
        ]
    }
    

    Execute the tsc command to compile, and the compiled file structure will be as follows.

    1
    2
    3
    4
    5
    6
    7
    
    learnTsConfig/
        src/
            index.ts
            index.js
        outerIndex.ts
        outerIndex.js
        tsconfig.json
    
  2. include & exclude

    If there are few files in the project, using the files option to set the target files to be compiled is a good choice, but when there are a lot of files or the project files are updated frequently, writing all the files to be compiled in the files array is a bit tricky, and you have to update the files option every time you add a ts file.

    So ts also provides include option, which is similar to files, but you can use pattern match to delete the previously compiled js files and change the contents of the tsconfig.ts file as follows.

    1
    2
    3
    4
    5
    
    {
        "include": [
            "src/*.ts"
        ]
    }
    

    Execute tsc compilation, the file structure is as follows, only index.ts in the src/ directory is compiled.

    1
    2
    3
    4
    5
    6
    
    learnTsConfig/
        src/
            index.ts
            index.js
        outerIndex.ts
        tsconfig.json
    

    exclude does the opposite of include, it is used to exclude certain files, it also supports pattern matching, clean up the js file and update the tsconfig.ts file as follows.

    1
    2
    3
    4
    5
    6
    7
    8
    
    {
        "include": [
            "*.ts"
        ],
        "exclude": [
            "src/*.ts"
        ]
    }
    

    The include option means that all ts files in the root directory are compiled, and exclude means that all ts files in the src/ directory are excluded, so the compiled file structure of tsc is as follows.

    1
    2
    3
    4
    5
    6
    
    learnTsConfig/
        src/
            index.ts
        outerIndex.ts
        outerIndex.js
        tsconfig.json
    

    By default typescript will automatically look for .ts files and .d.ts files if you set the allowJS compile option (described later) to true, and will also look for .js files if you set the allowJS compile option (described later) to true. src/**/* is equivalent to src/**/*.ts and src/**/*.d.ts (and src/**/*.js if allowJs is true).

    There are some folders that typescript will automatically exclude, such as node_modules, bower_components, jspm_packages and <outDir>. If you want to force ts to compile ts files in these folders, you need to specify the files file option.

Compiler Options

Compiler options are the relevant configuration under the compilerOptions field.

Output files

  1. outDir

    By default, ts compiled js files are in the same directory as the source files. Use the outDir option to specify the directory where the compiled files are located. Clean up the js files generated by previous compilation.

    1
    2
    3
    4
    5
    
    learnTsConfig/
        src/
            index.ts
        outerIndex.ts
        tsconfig.json
    

    Update the tsconfig.json file.

    1
    2
    3
    4
    5
    6
    7
    8
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist"
        }
    }
    

    Then execute the tsc command to compile, after compiling, the dist/ folder will be generated, the dist/ directory is the compiled js file, the structure of the directory is the same as the project directory structure.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    learnTsConfig/
        dist/
            src/
                index.js
            outerIndex.js
        src/
            index.ts
        outerIndex.ts
        tsconfig.json
    
  2. rootDir

    The default root directory of typescirpt project is the directory where the tsconfig.json file is located, and all relative paths are relative to this root directory. We can change the project’s root directory location with the rootDir option. Delete the dist folder and update the tsconfig.json file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "rootDir": ".."
        }
    }
    

    Execute the tsc command and the compiled directory will be as follows.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    learnTsConfig/
        dist/
            learnTsConfig/
                src/
                    index.js
                outerIndex.js
        src/
            index.ts
        outerIndex.ts
        tsconfig.json
    

    In most cases, we just keep the default behavior of TypeScript and use the tsconfig.json file located in the root of the project.

  3. removeComments

    The removeComments option is used to remove commented code from the compiled js file.

    First clean up the project and update the tsconfig.json file as follows.

    1
    2
    3
    4
    5
    6
    7
    8
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
        }
    }
    

    Update the contents of the src/index.ts file.

    1
    2
    3
    4
    5
    6
    
    type FuncType = () => void;
    
    // print info: Hello Ts
    const sayHello: FuncType = () => {
        console.log("Hello Ts");
    };
    

    tsc is compiled, and the compiled dist/src/index.js file reads as follows.

    1
    2
    3
    4
    
    // print info: Hello Ts
    var sayHello = function () {
        console.log("Hello Ts");
    };
    

    You can see that the comments have not been removed. Update the tsconfig.json file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true
        }
    }
    

    Compile again, and the compiled dist/src/index.js file is as follows.

    1
    2
    3
    
    var sayHello = function () {
        console.log("Hello Ts");
    };
    

    You can see that the comment content has been removed.

  4. module

    Suppose you are developing a project that needs to run in a nodejs environment, and in the project you use import to introduce modules, but nodejs does not support it. nodejs uses the CommonJS module system. To convert the compiled js file import statements to require statements, you can configure "module": "CommonJS" .

    Here, let’s try it manually. Update the tsconfig.js file.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "module": "CommonJS"
        }
    }
    

    Add the add.ts file to the src directory with the following content.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    /**
     * Add two numbers
     * @param a a number
     * @param b a number
     * @returns {number} sum
     */
    export const add = (a: number, b: number):number => {
        return a + b;
    };
    

    Update the src/index.ts file.

    1
    2
    3
    
    import {add} from "./add"
    
    console.log(add(3, 5));
    

    Compile the file, look at dist/src/index.js content as follows, you can see that the import statement has been converted to a require statement.

    1
    2
    3
    4
    
    "use strict";
    exports.__esModule = true;
    var add_1 = require("./add");
    console.log(add_1.add(3, 5));
    
  5. outFile

    outFile can specify that the compiled result file is packaged as a bundle, i.e. a js file, provided that the module option is set to System or AMD. If you want to support other module options, you can use tools like webpack, parcel, etc.

    For a simple experiment, update the tsconfig.json file as follows.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outFile": "dist/bundle.js",
            "removeComments": true,
            "module": "AMD"
        }
    }
    

    Only the dist/bundle.js file is generated after compilation.

source map

  1. sourceMap

    The source-map file represents a mapping relationship between the compiled source file and the output result file, which plays a very important role in debugging the project and allows us to display the source code in the browser developer tools for debugging. If the debugger looks at the compiled code, then debugging is such a painful thing.

    The source-map file is automatically generated by the compiler tool and ends with the .map suffix, it is a JSON file with the following structure.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    {
        "version": 3,
        "file": "bundle.js",
        "sourceRoot": "",
        "sources": [
            "../outerIndex.ts",
            "../src/add.ts",
            "../src/index.ts"
        ],
        "names": [],
        "mappings": "AAAA,IAAM,SAAS..."
    }
    

    The file field indicates the name of the output file corresponding to the source-map file, and the sources field indicates the compiled source file. The mapping attribute is a base64 encoded value that represents the relationship between the source file and the output file.

    And the compiled output file will have a comment at the end of the sourceMappingURL field, indicating the map file location, and this comment will be read by the browser to locate the map file.

    1
    2
    3
    4
    
    // b.js
    var b = 'B';
    
    //# sourceMappingURL=b.js.map 
    

    To generate the source-map file, you can set the sourceMap field to true.

    Update the tsconfig.json file.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outFile": "dist/bundle.js",
            "removeComments": true,
            "module": "AMD",
            "sourceMap": true
        }
    }
    

    Execute the tsc command, which will generate dist/bundle.js and dist/bundle.js.map after compilation.

  2. inlineSourceMap

    The sourceMap option generates a separate .map file for the compiled js file. By setting inlineSourceMap to true, you can avoid generating .map files and inline the map directly into the compiled js file.

    Update the tsconfig.json file.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outFile": "dist/bundle.js",
            "removeComments": true,
            "module": "AMD",
            "inlineSourceMap": true
        }
    }
    

    After compiling, view the compiled dist/bundle.js file.

    1
    2
    3
    
    ...
    
    //# sourceMappingURL=data:application/json;base64,...
    

    You can see that the sourceMappingURL is directly followed by the base64 data (map file content).

type declaration

The most important role of typescript is to make js support types and turn it into a strongly typed language.

  1. declaration

    Set the declaration field to true to automatically generate declaration files.

    Update the tsconfig.json file.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "declaration": true
        }
    }
    

    Executing the tsc command to compile, you can see the dist/**/*.d.ts file generated, which is the declaration file for the corresponding *.js file. With these declaration files, the ts compiler can know the API structure of the package, even if the compiled JavaScript file does not contain any type information.

    The directory of the generated dist files is as follows.

    1
    2
    3
    4
    5
    6
    7
    8
    
    dist/
        src/
            add.d.ts
            add.js
            index.d.ts
            index.js
        outerIndex.d.ts
        outInder.js
    
  2. declarationDir

    When declaration is set to ture, the ts compiler puts the corresponding .d.ts file into the same level as the compiled js file. You can put all declaration files in the same directory by setting declarationDir.

    Update the tsconfig.json file as follows.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "declaration": true,
            "declarationDir": "dist/types", 
        }
    }
    

    Execute the tsc command, you can see the dist/types/ directory is generated, the structure of the directory is the same as the source file directory, except that they are all .d.ts declaration files.

  3. lib

    typescirpt has some built-in TypeScirpt declaration files, such as Promise, Object.freeze and the declaration of the browser API. These declaration files can provide code hints and warnings. They are usually stored in the lib folder, which we call the standard library. You can manually select which libraries to import by setting the lib field.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "declaration": true,
            "declarationDir": "dist/types", 
            "lib": [ "ES5", "ES2015.Promise", "DOM" ]
        }
    }
    
  4. typeRoots

    When you publish your typescript program, as an npm package, you may publish the compiled JavaScript package, so that non-typescript programs can introduce the npm package, in order to provide declaration information, you can also provide the corresponding declaration file, so that typescript compilers and IDEs (such as vscode) can provide type hints, error hints based on the declaration file. To generate the declaration file, you just need to set declaration to true.

    But not all programs are written in typescript, for example lodash, which itself is written in javascript, so it can’t use the function provided by ts to generate the declaration file automatically. So you need to manually provide declaration files for npm packages that don’t have them.

    The DefinitelyTyped community’s job is to provide declaration files for the more popular npm packages that don’t have them. You can provide a declaration file for an npm package by installing a declaration file package that starts with @types.

    For example npm install @types/lodash, @types/lodash is the declaration file for the lodash package.

    By default, typescript imports all type declarations from the node_modules/@types folder into the global space, but note that only declarations in the script file will be imported into the global space, the module file is hidden from the global space.

    type-root is the directory where the package declaration files are stored, and can be set to a series of file paths via the typeRoots option, indicating where typescript imports type information from, the default value is node_modules/@types.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "declaration": true,
            "declarationDir": "dist/types", 
            "typeRoots": ["./my-types"]
        }
    }
    

    By setting "typeRoots": [". /my-types"], typescript will only import declarations from the my-types folder, not from the node_modules folder.

  5. types

    typeRoots is used to import all declarations in the directory into the global space, but if types is set, only the package declarations specified by types will be imported into the global space.

    1
    2
    3
    4
    5
    6
    
    {
        "compilerOptions": {
            "outDir": "dist",
            "types": [ "node", "moment" ] // 导入node_modules文件夹下的@types/node和@types/moment,其他包将会被忽略
        }
    }
    

JavaScript compilation

By default, typescript is compiled without the js file. This default behavior can be changed with allowJS and checkJS.

  1. allowJS

    When you introduce a module in a typescript file with an import statement, such as import {add} from ". /add, by default the ts compiler will automatically look for src/add.ts and src/add.d.ts and it will not consider src/add.js, we can change this default behavior by setting allowJS to true.

    First, update the tsconfig.json file as follows.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "declaration": true,
        }
    }
    

    Create a new src/add.js and enter the following code.

    1
    2
    3
    
    export const add = (a, b) => {
        return a + b;
    };
    

    Introduce the add function in src/index.js.

    1
    2
    3
    
    import {add} from "./add";
    
    console.log(add(3, 5));
    

    By default, allowJS is false, so the compiled add.js file will not be included in the dist/src/ directory after the tsc compilation.

    Update the tsconfig.json file to set allowJS to true.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "declaration": true,
            "allowJs": true
        }
    }
    

    Recompile, and after compiling, add.d.ts and add.js files will be added to the dist/src/ directory.

    So, if you want your project to support js files, just set "allowJs": true.

  2. checkJs

    Using allowJS allows the compiler to include js files in the compilation stage, but the compiler does not type check the js files. Type checking is an important feature of ts that greatly improves our development efficiency, so in order to allow the ts compiler to type check js files, you need to set "checkJS": true.

    To explain further, first add const num = parseInt(1.5); to the top of add.js.

    Then compile it with tsc and it compiles successfully.

    Then update the tsconfig.json file.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    {
        "include": [
            "**/*.ts",
        ],
        "compilerOptions": {
            "outDir": "dist",
            "removeComments": true,
            "declaration": true,
            "allowJs": true,
            "checkJs": true
        }
    }
    

    Compile with tsc again and the compilation should report an error.

    1
    2
    3
    4
    5
    6
    
    src/add.js:1:22 - error TS2345: Argument of type '1.5' is not assignable to parameter of type 'string'.
    
    1 const num = parseInt(1.5);
                        ~~~
    
    Found 1 error.
    

    Because checkJS is true at this point, the ts compiler will type check the js file, and the parseInt function accepts a string as an argument, but 1.5 is of type number, so the type is not compatible, so the compilation fails. If you are using vscode editor with checkJS enabled, the editor should give you a smart error when you hit the code const num = parseInt(1.5);.

III. Summary

There are many configuration fields in tsconfig, this article aims to introduce its basic usage and basic structure, and does not cover all of them. I hope that through this article, you can understand tsc compiler, know how to configure tsc compiler and understand its principles.

For more tsconfig configuration, please refer to TSConfig Reference.