tsconfig & Compiler Options
A tsconfig.json file is the configuration that tells the TypeScript compiler which files to include and how to check and build them — controlling strictness, the output JavaScript version, the module system, and where compiled files go.
Learn tsconfig & Compiler Options in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
tsconfig.json is the settings panel on a power tool . strict is the full set of safety guards — slower to get used to, but it stops you losing a finger. target is the speed dial: how modern the output runs. lib is which attachments the tool knows it has fitted. outDir / rootDir are the in-tray and out-tray that keep raw stock and finished parts separate. You configure the panel once per project, and every build afterward follows those rules — so the whole team gets the same checks and the same output.
This is JSON, not runnable code — it's the file tsc reads before compiling. Each option is annotated:
1. Strict Mode & strictNullChecks
Setting "strict": true flips on a bundle of checks. The flagship is strictNullChecks : null and undefined stop being assignable to every type and become values you must handle explicitly. That single change eliminates a huge share of "Cannot read property of undefined" crashes:
2. noImplicitAny
Also part of strict , noImplicitAny turns "I couldn't figure out this type, so I'll silently call it any " into an error. It forces you to annotate parameters the compiler can't infer, closing the door on values that quietly do the wrong thing at runtime:
3. target , module & lib
These three decide what your compiled output looks like. target is the JavaScript version emitted (modern syntax is kept; older targets down-level it). module is the output module system (ES modules vs CommonJS). lib is the set of built-in API type definitions the checker is allowed to assume exist:
🎯 Your Turn
Write the null/undefined guard that strictNullChecks would require before using a value. Fill in the blanks and match the expected output.
Write a config reader that never crashes on a missing key or a missing config — the kind of defensive code strictNullChecks pushes you toward. Follow the outline, run it, and match the example output.
Practice quiz
What is a tsconfig.json file?
- A runtime config loaded by your app
- A package manifest
- The configuration telling the compiler which files to include and how to check/build them
- A test runner config
Answer: The configuration telling the compiler which files to include and how to check/build them. tsconfig.json controls strictness, output JS version, module system, and file layout for tsc.
What does 'strict: true' do?
- Enables a whole family of strict checks at once
- Enables one check
- Disables all checks
- Only affects formatting
Answer: Enables a whole family of strict checks at once. It turns on strictNullChecks, noImplicitAny, strictFunctionTypes, and several more together.
What does strictNullChecks change?
- It removes null at runtime
- It allows null everywhere
- It converts null to 0
- null/undefined become separate types you must handle before use
Answer: null/undefined become separate types you must handle before use. null and undefined stop being assignable to every type, eliminating many undefined crashes.
What does noImplicitAny do?
- Bans the any keyword entirely
- Makes a value the compiler can't infer a type for an error
- Adds any to everything
- Only warns on functions
Answer: Makes a value the compiler can't infer a type for an error. It forces you to annotate values that would otherwise be silently any.
What does the 'target' option control?
- The JavaScript language version TypeScript emits
- The module system
- Which files compile
- The lib APIs
Answer: The JavaScript language version TypeScript emits. target sets the emitted JS version; older targets down-level modern syntax.
What does the 'module' option control?
- The JS version
- The strictness level
- The module system of the output (ESNext, CommonJS, etc.)
- The output folder
Answer: The module system of the output (ESNext, CommonJS, etc.). module decides whether import/export stay as ES modules or become require().
What does the 'lib' option control?
- The output directory
- Which built-in API type definitions the checker knows (DOM, ES2017, etc.)
- The module system
- The strict flags
Answer: Which built-in API type definitions the checker knows (DOM, ES2017, etc.). lib lists known APIs; e.g. DOM makes document/window typed, ES2017 adds Object.entries.
What do rootDir and outDir do?
- Set strictness
- Pick the target
- Control imports
- rootDir is where source begins; outDir is where compiled files go
Answer: rootDir is where source begins; outDir is where compiled files go. They mirror your source structure into the output folder when tsc emits files.
Why does esModuleInterop exist?
- To speed up compilation
- To let you write natural default imports from CommonJS modules
- To enable strict mode
- To freeze imports
Answer: To let you write natural default imports from CommonJS modules. It maps CommonJS module.exports cleanly so 'import React from "react"' works.
In a Vite/bundler setup, how is tsc often used?
- To bundle the app
- Not at all
- With --noEmit, just for type-checking while the bundler produces output
- To minify code
Answer: With --noEmit, just for type-checking while the bundler produces output. The bundler handles output; tsc --noEmit is run purely to type-check.