๐ŸŽ“ 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?