[Part 2] What the tsconfig.json! - Exploring the most useful compiler options

[Part 2] What the tsconfig.json! - Exploring the most useful compiler options

·

5 min read

The compilerOptions setting is one of top-level options of the TypeScript configuration file. Typescript provides a wide range of compiler options that serve various purposes, such as type checking, module resolution, code emission, JavaScript support, language features and environment settings, and so on. In this part of the series “What the tsconfig.json!“, we will explore the most basic and useful settings we should be familiar with when working on a TypeScript project.

1. Type checking

{
    "compilerOptions": {
        "noImplicitAny": true ,
        "noUnusedLocals": true ,
        "noUnusedParameters": true ,
        "strict": true,
    }
}

noImplicitAny: When a variable, parameter or return value cannot have its type inferred, TypeScript will implicitly assign the type any to it. If this setting is enabled, TypeScript will throw an error for such implicit any types, encouraging us to explicitly define the type.

noUnusedLocals: If this setting is enabled, TypeScript will report an error for any local variables that are declared but not used within the same scope.

function sum(a: number, b: number){
    const sum = a + b; // Error: 'sum' is declared but its value is never read.
    return a + b; 
}

noUnusedParameters: If this setting is enabled, TypeScript will report an error for any function or method parameters that are declared but not used in the implementation

function sum(a: number, b: number, c: number){
  // Error: 'c' is declared but its value is never read.
    return a + b;
}

strict: If this setting is turned on, it will enable all strict mode family options as shown below:

{
    noImplicitAny: true,
    strictBindCallApply: true,
    strictBuiltinIteratorReturn: true,
    strictFunctionTypes:  true,
    strictNullChecks: true,
    strictPropertyInitialization: true,
    noImplicitThis: true,
}

2. Module resolution

module: This option specifies the module syntax to use in our compiled code.

// Your code base
import { sum } from "./utils";
export const twoSum = (a: number,b: number) => sum(a,b) * 2;

// If module: commonjs. Then compiled code:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoSum = void 0;
const utils_1 = require("./utils");
const twoSum = (a, b) => (0, utils_1.sum)(a, b) * 2;
exports.twoSum = twoSum;


// If module: {ESNext|ES2015|ES6|ES2020|ES2022}. Then compiled code:
import { sum } from "./utils";
export const twoSum = (a,b) => sum(a,b) * 2;

moduleResolution: This option specifies how TypeScript resolve the module path. The allowed values include:

node/node12: Designed for Node.js version older than v10, which only supports CommonJS. When using this settings we’re able to omit file extension and index file.

import sum from './utils/sum'; // Instead of ./utils/sum.js
// Or
import { sum } from './utils'; // If there is a directory '/utils' with an 'index.ts' file

node16/nodenext: Designed for Node.js version 12 and above, which supports both ES import and CommonJS require:

  • .mjs and .cjs files are always interpreted as ES modules and CJS modules, respectively.

  • .js files are interpreted as ES modules if the nearest package.json file contains a type field with the value "module" , otherwise as CommonJS.

  • Not allowed to omit file extensions or index.js suffixes.

  • For node16 and nodenext, module and moduleResolution go hand-in-hand.

bundler : intended to use with bundlers like Webpack, Rollup, or Vite. Similar to node16/nodenext, this mode supports package.json imports and exports. And this mode never requires file extensions on relative paths in imports.

paths: Allows us to define custom module resolution paths.

{
    "compilerOptions": {
        "paths": [
        {"utils/*": "src/utils"}
        ]
    }
}

3. Code emission

declaration: Enabling this setting on will instruct TypeScript to generate d.ts (declaration) files along sides compiled Javascript files. These files provide type information for our porject.

declarationDir: This setting defines the directory where d.ts files should be located

{
  "compilerOptions": {
    "declaration": true,
    "declarationDir": "./types"
  }
}

noEmit: Enabling this setting prevents the TypeScript compiler from emitting JavaScript files. This is often used when TypeScript is being used for type-checking only.

4. JavaScript support

allowJs: Enabling this setting allows us to use .js files in the TypeScript projects.

5. Interop constraints

isolatedModules: Turning this setting on ensures each file can be transpiled independently, without relying on information from other files.

forceConsistentCasingInFileNames: This setting ensures that file names are consistently cased across the project, preventing issues related to case sensitivity, especially in environments where the file system is case-insensitive.

6. Language and environment

jsx: This setting specifies how JSX code compiled in generated Javascript files. It only appies for .tsx files. Common options for this setting includes:

preserve: Emit .jsx files and keep JSX code unchanged. This is useful when another tool (like Babel) will process JSX code further.

react: Emit .js files and transforms the JSX code to React.createElement calls.

lib: Tells TypeScript what built-in type definitions to include in our project.

//If your code runs in the DOM,
{
    "lib": ["es2022", "dom", "dom.iterable"]
}
// If your code does no run in the DOM,
{
    "lib": ["es2022"]
}

target: This setting specifies which version of Javascript will compile to.

 {
  "compilerOptions": {
    "target": "es2022"
  }
}

7. Projects

composite: This flag must be true for referenced projects.

incremental: Turning this setting on will generate .tsbuildinfo files that store information about the last compilation.

8. Completeness

skipLibCheck: Enabling this setting will skip checking the type of .d.ts files, which improve the performance of the TypeScript compiler. If not, all libs in node_modules will be checked

That covers all essential compiler options, in my opinion. If you’d like to explore more settings, feel free to visit the official “TypeScript: TSConfig Reference - Docs on every TSConfig option