Also available in: Español · Português · Français · العربية
What TypeScript strict mode actually turns on
The nine options strict covers, the eight it does not, and the code each one lets through — checked by compiling, not by quoting.
What does strict: true do?
Setting strict to true in your tsconfig is a shorthand: it switches on a fixed group of individual compiler options rather than being a check of its own. In TypeScript 5.9 that group has exactly nine members — noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, strictBuiltinIteratorReturn, noImplicitThis, useUnknownInCatchVariables and alwaysStrict.
The list is worth reading from the compiler rather than from an article, because it grows. strictBuiltinIteratorReturn was added in TypeScript 5.6 and most write-ups still describe strict as seven or eight flags. This page takes the list from the compiler's own option declarations, so it follows TypeScript rather than the other way round.
The important part is what is not in the group. TypeScript has eight further options that catch real mistakes and that strict does not touch — including noUncheckedIndexedAccess, exactOptionalPropertyTypes and noImplicitOverride. A project with strict on is not a project with every check on, and the gap is bigger than most people expect.
How to use it
- Paste your tsconfig, or just the compilerOptions block. Comments and trailing commas are fine — a tsconfig is JSONC, not JSON, and this reads it the way tsc does. Either the whole file or a bare options object works.
- Read the two counts. How many of the nine strict covers are on, and how many of the eight it does not. Anything you switched off by hand is listed separately, because an explicit setting beats strict and nothing warns you.
- Look at the code samples under the eight. Each is a program that compiles cleanly with strict on and fails the moment that option is added. Copy the strictest config from the button if you want all seventeen.
The eight checks strict leaves off
Every option in that second list ships here with a program that demonstrates the gap, and each of those programs was compiled twice while this page was built: once under strict, where it must produce no errors at all, and once with the option added, where it must fail. A sample only appears because the compiler produced both results, so the claim is a measurement rather than an opinion.
The one people meet first is noUncheckedIndexedAccess. Under strict, reading xs[0] from a string array gives you a string, even though the array may be empty and the value may be undefined — indexing simply lies about it. Turning the option on makes the type string | undefined and the compiler starts asking you to check. It is the single largest source of runtime undefined in otherwise strict codebases.
exactOptionalPropertyTypes is the subtlest. With a type of { nickname?: string }, strict happily accepts { nickname: undefined } — so the difference between a property that is absent and one that is present and undefined disappears, which matters enormously if that object is about to be serialised or spread over a database row. noImplicitOverride catches a subclass method that shadows a parent method by accident, which is how a rename silently stops calling what you thought it called. noPropertyAccessFromIndexSignature turns env.DATABASE_URL back into env["DATABASE_URL"], so a typo in an environment variable name stops type-checking as a string.
The remaining four are less about types and more about dead or unreachable code: a switch case that falls through, a function that returns a value on one path and nothing on another, and locals or parameters nobody reads.
Honest limits
An explicit setting beats strict, in both directions, and this is the part that quietly bites. Writing strict true alongside noImplicitAny false really does silence implicit-any errors: the compiler accepts the combination without a word, and a config inherited from an older project can carry a hole like that for years. This page lists those separately, and tsc --showConfig will confirm it if you want a second opinion.
It does not follow extends. A tsconfig that inherits from a base file — a framework preset, a shared package — is only half the story, and this page reads what you paste rather than resolving the chain. Run tsc --showConfig in the project to see the resolved result, then paste that here.
The list is tied to a TypeScript version, shown next to the copy button. Options get added: if your compiler is newer than this page's, it may know about something not listed here. That is why the list is generated from the compiler rather than typed out, and why the version is on the page rather than left implicit.
Finally, turning everything on is not automatically right. noUnusedLocals in particular fights with work in progress, and several teams keep it in the editor rather than the build. The page shows you where you stand and what each option costs; it does not pretend the answer is always yes.
Why is it free?
Everything happens in your browser. A tsconfig can name internal paths, package registries and project structure, and none of it is sent anywhere — the file never leaves the tab.
There is no server cost to recover, so there is no account, no limit and no watermark.