TypeScript tsconfig and Setup: Configure a Project Correctly

TypeScript projects start with a configuration file named tsconfig.json. This file tells the TypeScript compiler how to find your source files, where to place compiled JavaScript, and which type-checking rules to apply.

Quick answer: tsconfig.json is the main configuration file for a TypeScript project. It controls compiler settings such as strict mode, input and output folders, and which files TypeScript should compile.

Difficulty: Beginner

You'll understand this better if you know: basic JavaScript files, how folders and file paths work, and the difference between source code and generated output.

1. What Is tsconfig.json?

tsconfig.json is a JSON file that defines a TypeScript project. When you run the TypeScript compiler in a folder containing this file, the compiler reads the settings and uses them for the whole project.

Without tsconfig.json, TypeScript still works for quick checks, but you lose most of the project structure and configuration that real applications need.

2. Why tsconfig Matters

A good TypeScript setup prevents confusion later in development. It helps you keep source files, generated files, and type-checking rules organized in one place.

TypeScript projects often grow quickly. A clear configuration makes it easier to:

In practice, tsconfig.json is the difference between a working local experiment and a maintainable project setup.

3. Basic Syntax or Core Idea

A minimal TypeScript configuration usually starts with tsc --init. That command creates a starter tsconfig.json file.

Creating the config file

tsc --init

This command creates a default configuration in the current directory. After that, TypeScript uses the file when you run tsc without extra file arguments.

A minimal project configuration

{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"strict": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}

Here, compilerOptions controls the compiler, include tells TypeScript which files belong to the project, and src is the folder containing your source code.

4. Step-by-Step Examples

Example 1: Set up a simple project structure

Start with a clean folder layout. Keep TypeScript source files in src and compiled files in dist.

project/
src/
index.ts
tsconfig.json

Then add a simple source file.

const message: string = "Hello, TypeScript!";
console.log(message);

When you run the compiler, TypeScript reads the config and generates JavaScript in the output directory.

Example 2: Compile into a separate output folder

This setup keeps generated JavaScript out of your source folder, which makes the project easier to manage.

{
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*.ts"]
}

This configuration says: take TypeScript files from src and place compiled output into dist.

Example 3: Enable strict type checking

Strict mode catches more mistakes before your code runs.

{
"compilerOptions": {
"strict": true
}
}

With strict mode on, TypeScript enforces safer checks such as possibly undefined values and implicit any usage.

Example 4: Add source files and keep build artifacts out

Use include and exclude together to control what the compiler sees.

{
"compilerOptions": {
"outDir": "dist"
},
"include": ["src/**/*"],
"exclude": ["dist", "node_modules"]
}

This prevents TypeScript from trying to compile generated files or installed packages.

5. Practical Use Cases

6. Common Mistakes

Mistake 1: Compiling the output folder again

One common setup problem is letting TypeScript read files from the build output directory. That can cause repeated compilation, confusing file lists, or stale artifacts.

Problem: If dist is included in the project, TypeScript may try to compile generated files as if they were source files.

{
"compilerOptions": {
"outDir": "dist"
},
"include": ["**/*"]
}

Fix: Limit input files to your source folder and exclude the build output directory.

{
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*"],
"exclude": ["dist"]
}

This works because TypeScript only sees the real source files.

Mistake 2: Expecting TypeScript to run without a config

Beginners sometimes run tsc in a folder that does not contain tsconfig.json and expect project behavior.

Problem: Without a project file, TypeScript uses default behavior and may report tsconfig.json-related workflow confusion such as “Cannot find a tsconfig.json file at the specified directory.”

tsc

Fix: Create a config file first, then run the compiler from the project root.

tsc --init
tsc

The corrected workflow works because the compiler now has project settings to read.

Mistake 3: Putting source and output in the same folder

When compiled JavaScript lands beside your TypeScript source, it becomes harder to tell which files you should edit.

Problem: If the same directory contains both .ts and generated .js files, it is easy to edit the wrong file or commit generated output by accident.

{
"compilerOptions": {
"outDir": "src"
}
}

Fix: Use a separate output folder such as dist.

{
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
}
}

A separate output folder keeps source and build files clearly separated.

7. Best Practices

Practice 1: Turn on strict mode early

Strict mode helps TypeScript catch problems before they become runtime bugs. It is usually easier to enable it at the start than to retrofit it later.

{
"compilerOptions": {
"strict": true
}
}

With stricter checks, you get clearer feedback while the codebase is still small.

Practice 2: Separate source and build output

Keeping src and dist separate reduces accidental edits and makes version control cleaner.

{
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
}
}

This layout also makes it easier to delete and rebuild output without touching your source code.

Practice 3: Keep the config small at first

New projects do not need every option turned on immediately. Start with the settings you actually need, then add more when a real requirement appears.

{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"strict": true
},
"include": ["src"]
}

A smaller config is easier to understand and less likely to contain conflicting options.

8. Limitations and Edge Cases

9. Practical Mini Project

Here is a small but complete TypeScript setup for a simple command-line script. It includes a project structure, configuration, and source file that compiles cleanly.

Project layout:

project/
src/
index.ts
tsconfig.json

tsconfig.json:

{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"strict": true,
"rootDir": "src",
"outDir": "dist",
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["dist"]
}

src/index.ts:

function greet(name: string): string {
return `Hello, ${name}!`;
}

const output = greet("TypeScript");
console.log(output);

Run the compiler from the project root. TypeScript reads the config, checks the code, and writes JavaScript to dist.

10. Key Points

11. Practice Exercise

Expected output: a working project where tsc produces JavaScript in dist without compiling build artifacts.

Hint: Use rootDir, outDir, include, and exclude together.

{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"strict": true,
"rootDir": "src",
"outDir": "dist"
},
"include": ["src/**/*"],
"exclude": ["dist"]
}

12. Final Summary

tsconfig.json is the foundation of a TypeScript project. It tells the compiler what to check, what to compile, and where to put the output. Once you understand the core options, you can keep your project consistent and easier to maintain.

The most important habits are simple: create a config with tsc --init, keep source files in src, send output to dist, and enable strict mode when possible. Those choices cover most everyday TypeScript setups.

From there, you can refine the config as your project grows by adding module settings, source maps, path aliases, or other options your build system needs. A clean setup today makes every later TypeScript change easier.