Quick Answer
With strict off in tsconfig.json, TypeScript stops checking for null and undefined, lets parameters silently become any, and skips several other checks. In VibeDoctor's scans, 10 of 78 TypeScript projects (13%) had a tsconfig.json that never turned strict on. Before TypeScript 6.0 that means strict mode is off. The fix is one line, "strict": true, followed by npx tsc --noEmit and working through the errors it reports.
How Often We See It
These numbers come from VibeDoctor's scans of the 336 projects connected to an account, as of each project's most recent scan (May to October 2026). The TypeScript count uses the 127 projects with a file-by-file language breakdown. No project or owner is identified.
| At the latest scan | Projects |
|---|---|
| TypeScript projects | 78 |
Neither strict nor noImplicitAny turned on |
10 (13%) |
TypeScript 6.0, released in March 2026, made strict default to true. On 6.0 and later, only an explicit "strict": false turns it off. On 5.x and earlier, leaving the line out means strict mode is off. Writing "strict": true explicitly is correct on every version.
We count a project as strict when any config in its chain turns strict or noImplicitAny on. That includes configs it extends or lists under references, which is how Vite templates and monorepos split their settings. A project that extends a preset we cannot read, such as an npm package, is not counted as off.
What TypeScript Strict Mode Actually Is
strict is a shorthand that turns on a family of compiler checks at once. Without it, TypeScript accepts many patterns that are normal in JavaScript but are common sources of runtime crashes.
The strict family:
strictNullChecks- requires explicit handling ofnullandundefinednoImplicitAny- stops variables and parameters from silently becominganystrictFunctionTypes- checks function parameter types properly when callbacks are passed aroundstrictBindCallApply- type-checksbind,callandapplystrictPropertyInitialization- ensures class properties are initialized in the constructornoImplicitThis- flagsthiswith an implicitanytypealwaysStrict- emits"use strict"in every output fileuseUnknownInCatchVariables- types caught errors asunknowninstead ofanystrictBuiltinIteratorReturn- stricter types for built-in iterators (TypeScript 5.6 and later)
Of these, strictNullChecks usually catches the most real bugs: it is the one behind "Cannot read properties of undefined".
One limit to know about: strictFunctionTypes does not apply to methods. The TypeScript docs explain that it covers functions written in function syntax only, because the team found many unsafe class hierarchies, including some in the DOM, while building it. So a type written as func(x: string | number): void still accepts a function that takes only a string, while func: (x: string | number) => void is rejected under strict mode.
Why AI-Generated Projects End Up With Strict Off
Strict mode makes the compiler complain about code that runs fine in the happy path: reading a property of something that might be undefined, or passing a loosely typed callback. When an AI assistant or a hurried developer hits a wall of type errors, turning strict off is the fastest way to a green build. The code still looks typed, but most of the safety is gone.
// BAD - tsconfig.json with strict disabled
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": false,
"skipLibCheck": true,
"moduleResolution": "bundler"
}
}
With this config, the following compiles with zero errors, bugs included:
// All of these compile with strict: false
function getUsername(user) { // implicit any - no error
return user.profile.name.trim(); // no null check - no error
}
const id = getUserId(); // could be undefined - no error
const record = records[id]; // undefined key - no error
console.log(record.createdAt); // crashes at runtime
What You Get With Strict Mode On
// GOOD - tsconfig.json: "strict": true
function getUsername(user: User): string {
if (!user.profile) return 'Anonymous'; // required by strictNullChecks
return user.profile.name?.trim() ?? '';
}
const id = getUserId();
if (id === undefined) throw new Error('No ID');
const record = records[id];
console.log(record?.createdAt ?? 'unknown');
With strict: true, TypeScript makes you deal with every possible null dereference, implicit any and unsafe callback at compile time, before a user hits the crash.
Strict Mode Impact by Flag
| Flag | What It Catches | Bug Class Prevented |
|---|---|---|
strictNullChecks |
Property access on values that may be null or undefined | Cannot read properties of undefined |
noImplicitAny |
Variables and parameters without a type | Untyped code bypassing every other check |
strictPropertyInitialization |
Class properties not assigned in the constructor | Fields used before they are set |
useUnknownInCatchVariables |
Reading .message on a caught error without narrowing |
Crash when something other than an Error is thrown |
strictFunctionTypes |
Incompatible callback signatures | Wrong argument type passed to callbacks |
How to Turn Strict Mode On in an Existing Project
On a large AI-generated codebase, switching strict on can produce dozens of errors at once. Work through them in stages:
- Turn strict on and list the errors: set
"strict": trueand runnpx tsc --noEmit, which type-checks without writing output files. - Fix
noImplicitAnyerrors first: usually the easiest, by adding types to parameters and variables. - Work through
strictNullChecks: for each error, decide whether the value can really benull. If yes, add a guard. If no, use the!assertion, but only where you are certain. - Mark what you cannot fix yet: put
// @ts-expect-errorwith a short reason on the line instead of turning strict off again. You get a searchable list of what is left. - Keep it on: VibeDoctor's Vibe Check reads your
tsconfig.json, followsextendsandreferences, and reports check CFG-007 when none of those configs turns strict on. Free to sign up.
In Next.js, also check next.config.js for typescript: { ignoreBuildErrors: true }. That setting lets next build succeed with type errors, so strict mode never blocks a broken deploy.
FAQ
Can I enable individual strict flags instead of the full strict bundle?
Yes. Every flag in the family can be turned on by itself. If strict: true produces too many errors at once, start with "strictNullChecks": true alone, then add the others one at a time as you clear the errors each one brings.
What is TS7053, and why does it disappear when strict is false?
TS7053 reads "Element implicitly has an 'any' type because expression of type 'string' can't be used to index type ...". It is a noImplicitAny error, so it appears whenever noImplicitAny is on, directly or through strict, and goes away only when both are off. Turning them off hides the problem rather than fixing it. Fix the index instead: type the key as keyof typeof colors, give the object an index signature such as Record<string, string>, or check name in colors before reading.
Why does strictFunctionTypes not check my methods?
By design. strictFunctionTypes applies only to functions written in function syntax, such as onChange: (value: string) => void, not to methods written as onChange(value: string): void. Write the type as a function property when you want parameters checked strictly.
Does strict mode slow down TypeScript compilation?
Barely. The extra analysis adds a little compile time, which is negligible next to the cost of a null reference error in production.
What is skipLibCheck and should I set it to false?
skipLibCheck: true skips type-checking the declaration files in node_modules. It is common, it speeds up builds, and it does not weaken checks on your own code. Setting it to false now and then can reveal type conflicts between package versions, but you do not need it off permanently.
How does strict mode interact with Supabase generated types?
Types generated with supabase gen types typescript work with strict mode, and strict mode makes them more useful: with strictNullChecks, TypeScript flags every nullable column you read without checking it first.
Does enabling strict mode require rewriting existing code?
No rewrite, but you do have to address each error the compiler reports. Most fixes are small: a null check, a type annotation, optional chaining. Each one corresponds to a real potential runtime bug. Strict mode does not create problems; it shows you the ones already there.