We use cookies to enhance your experience on the site
CodeWorlds

TypeScript configuration and tools

In Jurassic Park, even the best genetic system is useless without proper calibration of the laboratory equipment. Similarly, TypeScript without proper configuration won't reach its full potential. The

tsconfig.json
file is your control panel — it defines how the TypeScript compiler interprets and transforms your code.

tsconfig.json — command center

Every TypeScript project starts with a

tsconfig.json
file in the root directory. This is a JSON file defining compiler options, which files should be compiled, and how the output should look:

1{
2  "compilerOptions": {
3    "target": "ES2020",
4    "module": "ESNext",
5    "lib": ["ES2020", "DOM", "DOM.Iterable"],
6    "outDir": "./dist",
7    "rootDir": "./src",
8    "strict": true,
9    "esModuleInterop": true,
10    "skipLibCheck": true,
11    "forceConsistentCasingInFileNames": true
12  },
13  "include": ["src/**/*"],
14  "exclude": ["node_modules", "dist"]
15}

Key compiler options

Target — output JavaScript version:

  • ES5
    — compatibility with older browsers
  • ES2020
    — modern environments (nullish coalescing, optional chaining)
  • ESNext
    — latest features

Module — module system:

  • CommonJS
    — Node.js (
    require
    /
    module.exports
    )
  • ESNext
    — ES modules (
    import
    /
    export
    )
  • NodeNext
    — Node.js with ESM support

Lib — which APIs are available:

  • DOM
    — browser API (document, window)
  • ES2020
    — methods like
    Promise.allSettled
    ,
    BigInt
  • WebWorker
    — Web Workers API

Strict Mode — maximum safety

The

strict: true
flag enables all rigorous checks at once. It's like turning on full security in Jurassic Park — no dinosaur will escape the enclosure:

1// strict: true enables ALL of the following:
2{
3  "strictNullChecks": true,       // null/undefined must be handled
4  "strictFunctionTypes": true,    // strict typing of function parameters
5  "strictBindCallApply": true,    // strict typing of bind/call/apply
6  "strictPropertyInitialization": true, // properties must be initialized
7  "noImplicitAny": true,          // implicit any is forbidden
8  "noImplicitThis": true,         // this must have a type
9  "alwaysStrict": true,           // "use strict" in every file
10  "useUnknownInCatchVariables": true // catch(e) is unknown, not any
11}

Example difference with

strictNullChecks
:

1// WITHOUT strictNullChecks — runtime error!
2function getDinoName(id: string): string {
3  const dino = dinosaurs.find(d => d.id === id);
4  return dino.name; // Runtime error: Cannot read property 'name' of undefined
5}
6
7// WITH strictNullChecks — TypeScript enforces null handling
8function getDinoName(id: string): string | undefined {
9  const dino = dinosaurs.find(d => d.id === id);
10  return dino?.name; // Safe — returns undefined if not found
11}

Path Aliases — navigation shortcuts

In large projects, imports can become unreadable. Path aliases allow you to create shortcuts:

1{
2  "compilerOptions": {
3    "baseUrl": ".",
4    "paths": {
5      "@models/*": ["src/models/*"],
6      "@utils/*": ["src/utils/*"],
7      "@services/*": ["src/services/*"],
8      "@config": ["src/config/index.ts"]
9    }
10  }
11}

Instead of:

1import { Dinosaur } from '../../../models/dinosaur';
2import { formatDate } from '../../utils/helpers';

You write:

1import { Dinosaur } from '@models/dinosaur';
2import { formatDate } from '@utils/helpers';

Declaration Files (.d.ts)

Declaration files describe types for JavaScript code. They have the

.d.ts
extension and contain no implementation — only type signatures:

1// dinosaur.d.ts — type declaration
2declare interface IDinosaur {
3  id: string;
4  name: string;
5  species: string;
6  dangerLevel: 1 | 2 | 3 | 4 | 5;
7}
8
9declare function findDinosaur(id: string): IDinosaur | null;
10declare const PARK_NAME: string;
11
12// Module declaration for a JS library without types
13declare module 'dino-tracker' {
14  export function trackPosition(id: string): [number, number];
15  export function getStatus(id: string): 'active' | 'sleeping' | 'escaped';
16}

Three types of declaration files:

  1. Automatic — TypeScript generates them with the
    declaration: true
    flag
  2. Manual — you write them yourself for JS code without types
  3. DefinitelyTyped — community types for popular libraries

DefinitelyTyped (@types/*)

Many JavaScript libraries don't have built-in types. The DefinitelyTyped repository contains community-created types:

1# Installing types for popular libraries
2npm install --save-dev @types/node
3npm install --save-dev @types/express
4npm install --save-dev @types/lodash
5npm install --save-dev @types/jest

TypeScript automatically recognizes

@types/*
packages — you don't need to import them. If a library has built-in types (like axios or date-fns), you don't need a separate
@types
package.

The

typeRoots
option in tsconfig controls where TypeScript loads types from:

1{
2  "compilerOptions": {
3    "typeRoots": ["./node_modules/@types", "./src/types"]
4  }
5}

ESLint with TypeScript

TypeScript has its own type checks, but ESLint with the

@typescript-eslint
plugin adds stylistic rules and advanced analysis:

1{
2  "parser": "@typescript-eslint/parser",
3  "plugins": ["@typescript-eslint"],
4  "extends": [
5    "eslint:recommended",
6    "plugin:@typescript-eslint/recommended",
7    "plugin:@typescript-eslint/recommended-requiring-type-checking"
8  ],
9  "parserOptions": {
10    "project": "./tsconfig.json"
11  },
12  "rules": {
13    "@typescript-eslint/no-explicit-any": "warn",
14    "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
15    "@typescript-eslint/prefer-nullish-coalescing": "error",
16    "@typescript-eslint/prefer-optional-chain": "error"
17  }
18}

Most important

@typescript-eslint
rules:

  • no-explicit-any
    — warns about using
    any
  • no-unused-vars
    — detects unused variables (with TypeScript support)
  • prefer-nullish-coalescing
    — prefer
    ??
    instead of
    ||
  • prefer-optional-chain
    — prefer
    a?.b
    instead of
    a && a.b
  • strict-boolean-expressions
    — forbids implicit boolean conversions

Code quality options

Additional compiler flags to help maintain code quality:

1{
2  "compilerOptions": {
3    "noUnusedLocals": true,        // error on unused variables
4    "noUnusedParameters": true,    // error on unused parameters
5    "noImplicitReturns": true,     // every path must return a value
6    "noFallthroughCasesInSwitch": true, // enforces break in switch
7    "noUncheckedIndexedAccess": true,   // arr[i] is T | undefined
8    "exactOptionalPropertyTypes": true  // undefined !== omitting a field
9  }
10}

The

noUncheckedIndexedAccess
option is particularly useful — it protects against indexing errors:

1const dinos = ["T-Rex", "Raptor", "Triceratops"];
2
3// WITHOUT noUncheckedIndexedAccess
4const first: string = dinos[0]; // OK, but dinos[100] would also be "string"!
5
6// WITH noUncheckedIndexedAccess
7const first: string | undefined = dinos[0]; // TypeScript enforces checking
8if (first) {
9  console.log(first.toUpperCase()); // Safe
10}
Go to CodeWorlds