Best Practices
Practical TSConfig guidance for Nova that uses small, composable preset chains. Favor explicit wiring and predictable compiler behavior.
Dos and Don'ts
- What: Use a layered
"extends"chain in this order: essentials → strict → role → runtime → framework → tool → your local overrides. - Why: The base loads first; the child overrides it. A clear order keeps policy layered and reviewable.
- What: Choose
role-app,role-config,role-scripts,role-source, orrole-testsimmediately after the strict layer. Reference-only solution files with"files": []do not compile files and need no role. - Why: The role decides whether TypeScript emits source, declarations, or nothing. Runtime and framework presets can then describe the environment without silently changing the build owner.
- What: Keep them in sync by using
"module": "nodenext"with"moduleResolution": "nodenext"for Node ESM, or"module": "esnext"with"moduleResolution": "bundler"for bundlers. - Why: Mismatched values make TypeScript and your runtime resolve imports differently, which causes "cannot find module" errors. Pairing keeps resolution consistent.
- What: Define import aliases in
pathswithout setting the deprecated TypeScript compilerbaseUrloption. - Why: TypeScript 6 resolves
pathsentries relative to the TSConfig file whenbaseUrlis absent.
- What: Path-related settings like
paths,rootDir,outDir,include, andexcludebelong in the app'stsconfig.jsonfile, not in Nova presets. - Why: TypeScript evaluates these against the file's location. Local wiring avoids resolution mistakes across different repos.
- What: Set
rootDirto the source directory for projects that usetscornova utility transpileto emit output. - Why: TypeScript 6 no longer lets emitted output layout depend on an inferred source root when that root differs from the TSConfig directory.
- What: Use
typesto list the type packages you installed (e.g.,@types/node,@types/react), or write[]when the config needs no ambient packages. - Why: Makes type sources explicit and under the app's control. Reduces surprises from transitive
@typesdependencies.
- What: If your project does not use
tscto build, selectrole-appand then add the matching framework or tool preset. - Why: The app role sets
noEmitwhile framework and tool layers provide their per-file compiler behavior. Each layer has one clear responsibility.
- What: Do not expect array settings like
libto spread values from the base. - Why: In
tsconfig, these arrays replace the parent. This is a config limitation, not JS behavior.
- What: Avoid settings that create unpredictability like
incremental,composite, andassumeChangesOnlyAffectDirectDependenciesin apptsconfig.jsonfiles. - Why: These introduce cache drift across environments. Prefer deterministic builds.
- What: Do not set
typeRootswithout a strong reason. - Why: It limits which
@typespackages are visible. Defaults usually work best.
Troubleshooting
Find issues by using the command below to print the effective config:
tsc --showConfig --project ./path/to/tsconfig.json
Related
- Review the supported compiler line and migration example in TypeScript Compatibility.