Best Practices
Practical TSConfig guidance for Nova that uses small, composable preset chains. Favor explicit wiring and predictable compiler behavior.
Dos and Don'ts
DO: Order presets intentionally
- What: Use a layered
"extends"chain in this order: essentials → strict → environment/framework → platform → tool → your custom overrides. - Why: The base loads first; the child overrides it. A clear order keeps policy layered and reviewable.
DO: Pair module with moduleResolution correctly
- 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.
DO: Pair baseUrl with paths
- What: Set
baseUrlwhen you define import aliases inpaths. - Why:
pathsrelies onbaseUrl. Editors and builds need both to resolve aliases correctly.
DO: Path-related settings belong in the app's tsconfig.json
- What: Path-related settings like
baseUrl,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.
DO: Declare ambient types explicitly
- What: Use
typesto list the type packages you installed (e.g.,@types/node,@types/react). - Why: Makes type sources explicit and under the app's control. Reduces surprises from transitive
@typesdependencies.
DO: Configure type-checking when a bundler transpiles
- What: If your project does not use
tscto build, set"isolatedModules": trueand"noEmit": truein the app'stsconfig.json. - Why: Bundlers and frameworks compile each file independently.
isolatedModulesenforces per-file safety.noEmitprevents TypeScript from writing JavaScript when another tool already emits output.
DON'T: Assume arrays merge/spread like JavaScript
- 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.
DON'T: Turn on cache-style settings
- What: Avoid settings that create unpredictability like
incremental,composite, andassumeChangesOnlyAffectDirectDependenciesin apptsconfig.jsonfiles. - Why: These introduce cache drift across environments. Prefer deterministic builds.
DON'T: Force typeRoots unless required
- 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