🎓 A1Learner
🔍
0 of 42 lessons completed

TypeScript tsconfig in Depth

The tsconfig file holds the compiler settings for a whole project. Its strict setting is a family switch, and each member of the family can also be set on its own.

The project config, one flag at a time

The config turns on the strict family and names its members one by one. It also adds the two extra checks and a paths mapping.

{
  "compilerOptions": {
    "target": "es2020",
    "module": "commonjs",
    "lib": ["es2020", "dom"],
    "outDir": "out",
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "useUnknownInCatchVariables": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "baseUrl": ".",
    "paths": {
      "@lib/*": ["./lib/*"]
    }
  },
  "include": ["main.ts"]
}

strictPropertyInitialization refuses an unset property

The class declares a string property but never sets it. Plain strict mode refuses the class.

class Profile {
  userName: string;

  show(): string {
    return this.userName;
  }
}

const profile = new Profile();
console.log(profile.show());

noUncheckedIndexedAccess refuses an unchecked read

Indexing an array may hit an empty slot, so the read has type number or undefined. Storing it in a number variable is refused.

const scores: number[] = [90, 85, 70];
const first: number = scores[0];
console.log(first);

noUncheckedIndexedAccess accepts a checked read

The cure checks for undefined before using the value. The same flag now accepts the program.

const scores: number[] = [90, 85, 70];
const first = scores[0];

if (first !== undefined) {
  console.log(first);
} else {
  console.log('no score');
}

Example

interface Settings {
  theme: string;
  retries: number;
}

const settings: Settings = { theme: 'dark', retries: 3 };
const labels: string[] = ['theme', 'retries'];
const firstLabel = labels[0];

console.log(settings.theme);
console.log(settings.retries);
if (firstLabel !== undefined) {
  console.log(firstLabel);
}

Key points

  • The strict flag turns on the whole strict family in one line.
  • The family members include noImplicitAny, strictNullChecks, strictPropertyInitialization, and useUnknownInCatchVariables.
  • strictPropertyInitialization requires every class property to be set in the constructor or at its declaration.
  • noUncheckedIndexedAccess adds undefined to the type of every index read, because the slot may be empty.
  • exactOptionalPropertyTypes treats a missing optional property and a property set to undefined as different states.
  • The paths setting maps an import prefix to a folder, so a short prefix can stand for a longer path.

In this example, the closing program compiles under the config from the first exhibit, guards its one index read, and prints the settings in order.

Note

A stricter config finds more mistakes at compile time and asks for more small checks in the code.

Try it Yourself

Edit the code, then press Run.

Running is simulated · TypeScript Playground

Exercise

What does noUncheckedIndexedAccess change about an index read?