2.4 tsconfig.json: Generating and Understanding the Defaults
Right, so you’ve got TypeScript installed. You can run tsc --version and feel a brief moment of power. Now you’re staring at an empty project directory. You might be tempted to just run tsc main.ts and call it a day. Don’t. That’s like using a particle accelerator to crack a walnut. It works, but you’re missing the point and you’ll eventually create a black hole that swallows your project whole. The proper way to wield this tool is with a tsconfig.json file. This is your project’s mission control, and we’re going to build it from the ground up.
The easiest way to start is to let the compiler generate a sensible default configuration for you. It’s a great first step because it gives you a complete, commented file to work with, rather than you staring at a blank text file and wondering which of the 100+ options you actually need.
Fire up your terminal in your project’s root directory and run:
tsc --init
Boom. You’ll now find a tsconfig.json file waiting for you. Open it. I’ll wait.
…See? I told you. It’s… a lot. It has every single option, most of them commented out. This is simultaneously helpful and overwhelming. Let’s cut through the noise and look at the few settings that are actually enabled by default. These are the ones the TypeScript team has decided are the best, most uncontroversial defaults for a modern project.
The Critical Defaults: What’s Actually On?
When you first generate the file, only a handful of options are uncommented. These are your foundation.
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Let’s break these down like we’re dissecting a frog in biology class, but with less formaldehyde.
"target": "es2016": This dictates what JavaScript version the compiler outputs. ES2016 is a safe, reasonably modern choice. It means your fancyasync/awaitcode gets translated into a clunky_generatorfunction pattern for older runtimes. If you know your code will run on a Node.js version or browser that supports ES2022, change this to"es2022"! You’ll get cleaner, more efficient output. This is the first setting I always change."module": "commonjs": This controls how your modules are structured.commonjsis therequire/module.exportssyntax used by Node.js. If you’re building for the web and using a bundler like Webpack or Vite, you might want"esnext"to use native ES modules (import/export)."esModuleInterop": true: This is a lifesaver. Back in the dark ages, JavaScript libraries couldn’t agree on how to export stuff. This flag cleans up the interoperability between CommonJS and ES modules. Just leave it ontrueforever. Trust me. The alternative is a world ofconst _ = require('lodash').defaultnonsense."strict": true: This is the big one. This single setting enables the entire full-power, seatbelts-required, no-nonsense TypeScript experience. It’s a meta-flag that turns on a whole suite of strict type-checking options. You should never, ever disable this. If your code doesn’t compile withstrict: true, the correct response is to fix your types, not to disable the safety features. This is the whole reason you’re here!"skipLibCheck": trueand"forceConsistentCasingInFileNames": trueare minor quality-of-life settings. The former speeds up compilation by skipping type checking of declaration files (*.d.ts), which is usually safe. The latter prevents the madness of having./myFile.tsand./myfile.tsin the same project, which can obliterate your sanity on case-insensitive filesystems.
Your First Real Compilation
Now, with your tsconfig.json in place, the magic happens. You don’t need to tell tsc what files to compile anymore. It will discover all the .ts files in your project directory and all subdirectories (thanks to the default "include" setting) and compile them according to your rules.
Create a simple main.ts file:
const greeting: string = "Hello, World!";
console.log(greeting);
Now, just run:
tsc
No arguments. Nothing. It finds your tsconfig.json, uses it, and compiles everything. You’ll get a main.js file. Run it with node main.js. Feel that? That’s the smooth, controlled power of a properly configured project. You’ve just graduated from hacking around to engineering.
The key takeaway: tsconfig.json is your blueprint. The generated one is a fantastic starting point. Tweak target and module to match your environment, and for the love of all that is good, never disable strict mode. Your future self, debugging a bizarre runtime error that would have been caught by the compiler, will thank you.