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?