A future TypeScript 6.0 is expected to be a disruptive major release. This article walks through every anticipated breaking tsconfig change, demonstrates the real-world errors developers will encounter, and provides a step-by-step migration guide.
How to Migrate Your tsconfig for TypeScript 6.0
- Audit your current tsconfig by running
tsc --showConfigto capture all resolved settings. - Remove all deleted and deprecated compiler options such as
outandsuppressImplicitAnyIndexErrors. - Set
strict: trueexplicitly, orstrict: falsewith individual flags enabled incrementally. - Specify
module,moduleResolution, andtargetexplicitly to avoid new inference defaults. - Run
tsc --noEmitand triage errors by category, starting withnoImplicitAny. - Fix strict null checks and property initialization errors using null guards or constructor injection.
- Update shared base tsconfig packages and CI pipeline version pins to 6.0-compatible versions.
- Clean up temporary
@ts-expect-errorcomments as permanent fixes are applied.
Note: TypeScript 6.0 is unreleased; verify all claims against official release notes before applying changes.
Table of Contents
Why a Future TypeScript 6.0 Will Demand a tsconfig Review
A future TypeScript 6.0 is expected to be a disruptive major release. Upgrading without updating your tsconfig will likely break builds, because the compiler is expected to ship with strict: true as the default, remove several legacy compiler options deprecated across the 5.x line, and shift module resolution inference logic. Projects that currently compile cleanly under implicit defaults may emit errors immediately after upgrading.
This article walks through every anticipated breaking tsconfig change, demonstrates the real-world errors developers will encounter across vanilla TypeScript, React (JSX), and Node.js projects, and provides a step-by-step migration guide. The final sections include example tsconfig files for React/Vite, Node.js, and monorepo projects, plus a reusable migration checklist.
What Is Expected to Change in TypeScript 6.0: A Summary of Anticipated Breaking Changes
strict: true May Become the Default
As of TypeScript 5.x, the strict flag in tsconfig.json defaults to false when absent. Projects that never explicitly set it benefit from lenient type checking. TypeScript 6.0 is expected to flip this: strict: true would become the implicit default when the flag is absent from configuration.
The strict meta-flag (as of TypeScript 5.x) controls eight individual checks: strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitAny, noImplicitThis, alwaysStrict, and useUnknownInCatchVariables. The set of flags under the strict umbrella can change between TypeScript minor versions, so verify the exact list against the release notes for the version you target. Any project that relies on the implicit strict: false default will suddenly have all strict checks enabled after upgrading, surfacing many new type errors.
Here is how the effective behavior would change for a minimal tsconfig:
Before (implicit strict: false — current behavior through TypeScript 5.x):
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"outDir": "./dist"
}
}
After (anticipated implicit strict: true in a future TypeScript 6.0):
The tsconfig file above would remain identical, but the compiler behavior would differ fundamentally. All strict sub-flags would be enabled by default. There is no visible change in the file; the change is in the compiler’s interpretation of the absent strict key.
Upgrading without updating your tsconfig will likely break builds, because the compiler is expected to ship with
strict: trueas the default, remove several legacy compiler options deprecated across the 5.x line, and shift module resolution inference logic.
Removed and Deprecated Compiler Options
TypeScript 6.0 is expected to remove several compiler options deprecated across the 5.x release line. The flags out and suppressImplicitAnyIndexErrors have issued deprecation warnings in recent 5.x releases, and the TypeScript team is expected to delete them entirely. Verify the deprecation timeline for each flag against the TypeScript release notes for 5.0 through 5.5 before relying on this information.
Note: Some earlier versions of this guide referenced a flag called
noStrictGenericChecks. This is not a documented TypeScript compiler option in any released version. It has been removed from this article.
When removed flags are present in tsconfig.json, TypeScript will trigger a hard error halting compilation entirely. For example:
{
"compilerOptions": {
"out": "./bundle.js",
"suppressImplicitAnyIndexErrors": true
}
}
Running tsc with the above configuration after the flags are removed would produce errors such as:
error TS5107: Option 'out' has been removed. Please remove it from your configuration.
error TS5107: Option 'suppressImplicitAnyIndexErrors' has been removed. Please remove it from your configuration.
There is no fallback or compatibility shim. The offending lines must be deleted.
No direct equivalent replacement exists for suppressImplicitAnyIndexErrors. However, noPropertyAccessFromIndexSignature (available since TypeScript 4.2) addresses related index signature access patterns and may cover some use cases. Evaluate whether enabling it fits your codebase’s needs.
New and Changed Compiler Flags
--erasableSyntaxOnly, introduced in TypeScript 5.5, relates to the Node.js type-stripping support introduced experimentally in Node.js 22.6.0. If your project targets Node.js type stripping, ensure you are on at least Node.js 22.6.0 and TypeScript 5.5+.
The --isolatedDeclarations flag, first introduced in TypeScript 5.5, may have updated default behavior that interacts with new strict defaults in a future 6.0. Projects relying on automatic declaration emit should set isolatedDeclarations explicitly if their build pipeline depends on it.
TypeScript 6.0 is expected to update the target and module default inference logic. When module is unspecified, the compiler may apply more opinionated defaults based on the target setting, favoring ESM semantics more aggressively than 5.x does.
{
"compilerOptions": {
"target": "es2022",
"module": "nodenext",
"moduleResolution": "nodenext",
"erasableSyntaxOnly": true,
"isolatedDeclarations": true
}
}
How strict: true as Default Would Affect Existing Projects
Implicit any Errors You Have Never Seen Before
The most common category of new errors after upgrading will be noImplicitAny violations. Functions that previously accepted untyped parameters without complaint will fail.
function processData(input) {
return input.trim().toLowerCase();
}
Under strict mode:
error TS7006: Parameter 'input' implicitly has an 'any' type.
Add explicit type annotations to fix it:
function processData(input: string) {
return input.trim().toLowerCase();
}
This pattern will appear across every untyped function parameter, callback argument, and destructured object in the codebase.
Strict Null Checks Breaking Your React Components
React components that access potentially undefined props or state values will fail under strictNullChecks. This is especially prevalent in components that consume optional props without null guards.
interface UserProfileProps {
user?: { name: string; email: string };
}
function UserProfile({ user }: UserProfileProps) {
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
Add a null guard before accessing the prop:
function UserProfile({ user }: UserProfileProps) {
if (!user) {
return <div>No user data available</div>;
}
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
strictPropertyInitialization in Node.js Classes
Node.js service classes that declare properties without initializing them in the constructor will fail strictPropertyInitialization:
class DatabaseService {
private connection: Connection;
private logger: Logger;
async connect() {
this.connection = await createConnection();
this.logger = new Logger();
}
}
Two approaches resolve this. Constructor initialization:
class DatabaseService {
private connection: Connection;
private logger: Logger;
constructor(connection: Connection, logger: Logger) {
this.connection = connection;
this.logger = logger;
}
}
Or a nullable type with a runtime guard when initialization must happen asynchronously:
class DatabaseService {
private connection: Connection | null = null;
private logger: Logger | null = null;
async connect(): Promise<void> {
this.connection = await createConnection();
this.logger = new Logger();
}
private assertConnected(): asserts this is this & {
connection: Connection;
logger: Logger;
} {
if (!this.connection || !this.logger) {
throw new Error(
"DatabaseService.connect() must be called before use."
);
}
}
async query(sql: string): Promise<unknown> {
this.assertConnected();
return this.connection.query(sql);
}
}
Warning: Avoid the definite assignment assertion (
!) for async initialization patterns. The!operator tells TypeScript to trust that the property is assigned before access, but the compiler cannot verify this for async workflows. If any method accesses the property before the async initializer completes, TypeScript will not warn you and a runtimeTypeErrorwill result. Prefer the nullable-type-with-guard pattern shown above, or constructor injection, so that the compiler can actually catch invalid access.
The Opt-Out Strategy: Explicitly Setting strict: false
For large codebases where immediate full-strict migration is not feasible, explicitly setting strict: false restores the pre-6.0 behavior. A more pragmatic approach enables individual strict flags incrementally:
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true,
"strictNullChecks": false,
"strictFunctionTypes": false,
"strictPropertyInitialization": false,
"strictBindCallApply": false,
"noImplicitThis": false,
"alwaysStrict": true,
"useUnknownInCatchVariables": false
}
}
Important:
strict: falsedisables the meta-flag but does not override sub-flags that are explicitly set totruein the same config. In the example above,noImplicitAny: trueandalwaysStrict: trueremain active regardless of thestrict: falsesetting. To fully restore lenient behavior, every sub-flag must also be explicitly set tofalse. The config above intentionally keepsnoImplicitAnyandalwaysStrictenabled as a starting point — enable additional flags one at a time as you fix each category.
This lets teams fix categories of errors in phases rather than confronting all strict checks simultaneously.
Step-by-Step tsconfig Migration Guide
Prerequisites
- Node.js: Version 18 or later recommended. If using Node.js type-stripping features, Node.js 22.6.0+ is required.
- npm (or compatible package manager): Version 7+ for workspaces support if using monorepos.
- TypeScript: Currently 5.x. Replace version references below with the actual 6.0 version string once released.
- Shell: Commands use Unix-style paths. Windows users should adjust paths or use WSL/Git Bash.
Step 1: Audit Your Current tsconfig.json
Before making changes, capture the resolved configuration:
npx tsc --showConfig
Example output (your values will vary):
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"outDir": "./dist",
"suppressImplicitAnyIndexErrors": true,
"esModuleInterop": true
}
}
Note: The
--showConfigoutput above is abbreviated for clarity. The real command also emitsfilesandincludearrays reflecting your resolved source file patterns. If you see both"files": []and"include": []in your output, it means TypeScript has resolved zero source files and will compile nothing — this is a misconfiguration, not normal behavior. Check that your tsconfig’sincludeorfilespatterns match your source directory.
Note that --showConfig shows resolved values. If strict is absent from your source tsconfig, it will not appear in the output under TypeScript 5.x (since it defaults to false). Under a future 6.0 where the default changes to true, the resolved value would show true even when absent from the source tsconfig.
Scan for any flags that appear in the removed options list and note which strict sub-flags are currently effective.
Step 2: Remove Deprecated and Deleted Options
Delete every removed flag. Replace deprecated patterns with modern equivalents where applicable. The out option was a predecessor to outFile, but most modern projects using bundlers should simply remove it entirely rather than substituting. If your project was using out for concatenation output, evaluate whether outFile meets your needs or whether your bundler handles this concern.
Before:
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"out": "./bundle.js",
"suppressImplicitAnyIndexErrors": true,
"esModuleInterop": true
}
}
After:
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true
}
}
Step 3: Decide Your Strict Mode Strategy
Option A embraces strict: true explicitly (recommended for greenfield or already well-typed projects):
{
"compilerOptions": {
"strict": true
}
}
Option B opts out and enables checks incrementally. Choose this when you need to keep the build green while fixing type errors in batches across sprints:
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true,
"alwaysStrict": true
}
}
Option C uses strict: true with targeted overrides for the most disruptive checks:
{
"compilerOptions": {
"strict": true,
"strictPropertyInitialization": false,
"useUnknownInCatchVariables": false
}
}
Option C works well for codebases over roughly 20k lines: it captures the majority of strict benefits while deferring the two checks that tend to produce the highest volume of errors in legacy code. The right strategy depends on your team’s capacity and codebase characteristics.
Step 4: Update module and target Settings
TypeScript 6.0’s anticipated updated inference logic means that leaving module unspecified may produce different behavior than in 5.x. Set these values explicitly.
Node.js project (ESM):
{
"compilerOptions": {
"target": "es2022",
"module": "nodenext",
"moduleResolution": "nodenext",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}
React + Vite project (requires TypeScript 5.0+ for moduleResolution: "bundler"):
{
"compilerOptions": {
"target": "es2022",
"module": "esnext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"skipLibCheck": true
}
}
Step 5: Run the Compiler and Triage Errors
npx tsc --noEmit
You may see output like:
src/utils/helpers.ts(12,24): error TS7006: Parameter 'data' implicitly has an 'any' type.
src/components/Header.tsx(8,14): error TS2532: Object is possibly 'undefined'.
src/services/auth.ts(22,3): error TS2564: Property 'client' has no initializer.
Your codebase determines the number and distribution of errors. Prioritize fixes by category. Address noImplicitAny errors first since they are the most numerous and typically the simplest to fix.
You can use // @ts-expect-error as a temporary escape hatch with a TODO comment for errors that require more significant refactoring:
const result = legacyFunction(untypedArg);
Note:
@ts-expect-errorsuppresses all errors on the annotated line, not just the one described in the comment. If a second, unrelated type error is introduced on the same line later, it will be silently swallowed. If the underlying error is later fixed and the line no longer produces a type error, TypeScript will report an “Unused ‘@ts-expect-error’ directive” error. This is actually a desirable property — it ensures these temporary suppressions do not silently persist once the issue is resolved. Keep suppressed expressions on their own line and review these comments regularly.
Step 6: Update CI/CD and Shared Configs
If the project extends shared base configurations like @tsconfig/recommended, @tsconfig/node20, or similar packages, verify that those packages have published 6.0-compatible versions once TypeScript 6.0 ships. Outdated base configs may reintroduce removed options or conflict with the new defaults.
Pin the TypeScript version in CI to avoid accidental upgrades breaking builds:
"devDependencies": {
"typescript": "5.5.0"
}
Replace
5.5.0with the actual TypeScript 6.0 version string once it is released and available on npm. As of this writing, no 6.x version exists on npm. Note: using an exact version (no~or^prefix) ensures that patch releases cannot inadvertently change type-checking behavior in CI.
For monorepos using project references, ensure each sub-project’s tsconfig has composite: true set and that the root tsconfig properly declares project references. The strict default change would apply to every tsconfig in the reference chain, so each sub-project must either embrace strict or explicitly opt out.
Complete tsconfig.json Examples for Common Stacks
React + Vite + TypeScript (6.0-Ready)
Note:
allowImportingTsExtensionsrequiresnoEmit: trueoremitDeclarationOnly: true. RemovingnoEmitwithout also removingallowImportingTsExtensionswill produce compiler error TS5096.
{
"compilerOptions": {
"target": "es2022",
"lib": ["es2022", "dom", "dom.iterable"],
"module": "esnext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"isolatedModules": true,
"allowImportingTsExtensions": true,
"noEmit": true
},
"include": ["src"]
}
Node.js API + TypeScript (6.0-Ready)
declarationMap generates source maps for declaration files, enabling “Go to Definition” in editors to navigate to the original .ts source rather than the .d.ts output.
{
"compilerOptions": {
"target": "es2022",
"lib": ["es2022"],
"module": "nodenext",
"moduleResolution": "nodenext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Full-Stack Monorepo Base Config
This root tsconfig acts as a solution file only; it does not compile source files directly. Each referenced package must have its own tsconfig with composite: true.
Warning: Frontend packages such as
packages/webmust overridemoduleandmoduleResolutionto"esnext"and"bundler"respectively, rather than inheriting"nodenext"from this base config. Usingmodule: "nodenext"for browser-targeted packages will cause module resolution errors.
{
"compilerOptions": {
"target": "es2022",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"references": [
{ "path": "./packages/shared" },
{ "path": "./packages/api" },
{ "path": "./packages/web" }
]
}
Note:
composite: trueis intentionally absent from this root solution file. Only the referenced sub-projects (packages/*) should setcomposite: truein their own tsconfigs. Settingcompositeon a root solution file that only declaresreferencescreates conflicting constraints (rootDirrequirements, file inclusion restrictions) that produce build errors.
TypeScript 6.0 Migration Checklist
- ☐ Back up or version-control your current tsconfig.json
- ☐ Run
tsc --showConfigto audit resolved settings - ☐ Remove all deleted/deprecated compiler options (
out,suppressImplicitAnyIndexErrors) - ☐ Explicitly set
strict: trueorstrict: false - ☐ If opting out of strict, enable individual strict flags incrementally
- ☐ Update
module,moduleResolution, andtargetexplicitly to avoid inference changes - ☐ Run
tsc --noEmitand categorize all new errors - ☐ Fix
noImplicitAnyerrors (add explicit types) - ☐ Fix
strictNullCheckserrors (add null guards / optional chaining) - ☐ Fix
strictPropertyInitializationerrors (initialize or use definite assignment) - ☐ Update shared/base tsconfig packages to 6.0-compatible versions
- ☐ Update CI pipeline TypeScript version pin (replace with actual 6.0 version once released)
- ☐ Remove temporary
@ts-expect-errorcomments as permanent fixes are applied - ☐ Communicate changes to the team and update contributing docs
Common Pitfalls and Troubleshooting
“Unknown compiler option” After Upgrade
A removed legacy flag is still present in your tsconfig.json. Delete the line. No direct equivalent exists for suppressImplicitAnyIndexErrors. However, noPropertyAccessFromIndexSignature (available since TypeScript 4.2) addresses related index signature access patterns and may cover some use cases.
Third-Party Library Type Errors Under Strict Mode
Older @types/* packages (e.g., older versions of @types/express or @types/lodash) sometimes ship with loose typings that do not survive strict mode. Use skipLibCheck: true as the pragmatic fix, which makes the compiler skip type-checking all .d.ts declaration files, including those generated by your own project. This can hide real bugs in your own declaration files, not just third-party ones. For cases where only standard library conflicts are the issue, consider the more targeted skipDefaultLibCheck: true instead. For persistent upstream issues, file issues on DefinitelyTyped so maintainers can tighten their type definitions.
IDE Not Reflecting New Settings
VS Code and WebStorm cache the TypeScript server version and resolved configuration. After upgrading TypeScript and modifying tsconfig, restart the TypeScript language server. In VS Code, open the command palette and select “TypeScript: Restart TS Server.” Verify the workspace is using the correct TypeScript version by checking the status bar.
Migrate Deliberately, Not Reactively
The TypeScript 6.0 migration will be manageable when approached systematically. Adopting strict: true fully, rather than opting out, catches null-reference and implicit-any bugs at compile time. Start with the audit, work through errors by category.
When TypeScript 6.0 is officially released, verify every claim in this article against the official TypeScript release notes before making changes to production projects.

