tsconfig.json explained for migrations
The compiler options that matter when you move a JavaScript project to TypeScript, what each one does, and sensible settings for each stage.
tsconfig.json controls how TypeScript reads and checks your project. During a migration, a handful of options matter far more than the rest. Here's what they do and how to set them at each stage.
The options that matter
| Option | What it does | During migration |
|---|---|---|
allowJs | Lets .js files be part of the program | true until the last file is converted |
checkJs | Type-checks .js files too | false while migrating; use --checkJs on the command line to measure |
strict | Turns on the full set of strict checks | false at first, then on, one flag at a time |
noEmit | Type-check only, don't write output | true if a bundler or runtime compiles your code |
module | Which module system to emit | NodeNext for Node; ESNext with a bundler |
moduleResolution | How imports are found | NodeNext for Node; Bundler with a bundler |
target | Which JavaScript version to emit | Match your runtime, e.g. ES2022 |
esModuleInterop | Smooths default imports from CommonJS packages | true |
resolveJsonModule | Allows importing .json files | true if you import JSON |
skipLibCheck | Skips checking .d.ts files in dependencies | true, for speed and fewer third-party errors |
baseUrl / paths | Import aliases such as @/utils | Copy from your bundler or jsconfig |
include | Which files belong to the project | Usually ["src"] |
Stage 1: starting out
Accept JavaScript, check nothing strictly, and change no output:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"allowJs": true,
"checkJs": false,
"strict": false,
"noEmit": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"skipLibCheck": true
},
"include": ["src"]
}Measure your baseline without changing the file:
npx tsc --noEmit --checkJsStage 2: migrating
Keep the config the same while files convert. Each converted .ts file is checked with the rules above, and the remaining .js files are allowed but not checked.
If you already have a jsconfig.json with paths, move those options into tsconfig.json and delete the jsconfig, so editor tooling and the compiler agree.
Stage 3: finishing
When no JavaScript is left:
{
"compilerOptions": {
"allowJs": false,
"strict": true
}
}Turn on strict gradually if the error count is high. See Turning on strict mode.
Bundlers and frameworks
If Vite, Next.js, webpack or another tool compiles your code, tsc should only check:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
"noEmit": true,
"jsx": "react-jsx"
}
}Frameworks often generate a starting config for you. Next.js, for example, writes one the first time it sees a .ts file. Keep its settings and add the migration options above.
Useful extras
"noUncheckedIndexedAccess": truemakesarray[i]possiblyundefined, catching a common class of bugs. Turn it on afterstrict."verbatimModuleSyntax": truemakes type-only imports explicit, which helps tools that compile files one at a time."incremental": truespeeds up repeated checks by caching results.
How CodeMorph uses your tsconfig
CodeMorph reads paths and baseUrl to resolve imports during Scan & Plan, and Run & Verify type-checks against your tsconfig.json, so your strictness is the bar every converted file has to meet.