AniUI Academy

Setting Up a TypeScript Project

Install TypeScript, generate a tsconfig.json, and understand what the compiler actually does with target, module and outDir before you write a line of typed code.

7 min read

Before writing any real TypeScript, it's worth knowing what's actually happening when you type tsc — because "the compiler" is doing two genuinely separate jobs, and conflating them is where a lot of confusion about TypeScript starts.

Installing TypeScript

TypeScript is a package like any other, installed per-project so everyone on a team (and CI) uses the same version:

npm install --save-dev typescript

That gives you a local tsc binary, runnable via npx tsc or an npm script. A global install (npm install -g typescript) works too, but ties your editor and terminal to whatever version happens to be installed globally — easy to drift out of sync with what a project actually expects.

tsconfig.json

A tsconfig.json file marks the root of a TypeScript project and configures the compiler. Generate a starting point with:

npx tsc --init

This produces a file with the most common options listed and mostly commented out, each with a one-line explanation. A minimal, deliberately chosen config looks like this:

{
  "compilerOptions": {
    "target": "es2020",
    "module": "esnext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["src"]
}

The include array is what tells the compiler which files are actually part of this project — without it, tsc walks the whole directory looking for .ts files, which usually means accidentally including things like config files or a dist folder from a previous build.

Two jobs, often split across two tools

tsc does two things at once by default: it checks your types, and it emits JavaScript. Historically that was one tool doing both. Today, a lot of projects split the two:

  • A fast, type-unaware transpiler (esbuild, SWC, or whatever a framework's build tool wraps) strips types and produces the actual shipped JavaScript, because it doesn't need to understand the type system to erase annotations — it just deletes them.
  • tsc --noEmit runs separately, purely as a type-checking pass, usually in CI or a pre-commit hook, catching type errors the fast transpiler would happily ignore.

This split exists because type-checking a large project is comparatively slow — it has to resolve every type across every file — while erasing annotations is nearly instant. Splitting them means the fast path (what actually blocks you from seeing your code run) stays fast, and the slow, thorough path still runs, just not on your hot reload loop.

Running TypeScript directly, without a separate build step

For quick scripts, a few tools let you run .ts files directly during development without a manual compile step first — tsx, ts-node, or the runtime's own built-in support in newer versions of Node.js and Deno. Under the hood these still strip types before execution; they just do it on the fly instead of as a separate command you run first.

npx tsx script.ts

This track's playgrounds work the same way: the code you write runs through type-checking and gets executed, in the browser, without you ever needing a local tsc install.

Where errors actually show up

In day-to-day work, most type errors are never seen via the terminal at all. Editors like VS Code run TypeScript's own "language service" continuously in the background — the same checker tsc uses — which is why a mismatched type turns red under your cursor the moment you type it, long before you'd run any command.

Try it yourself

This playground already has type-checking wired up. Introduce a real type error and watch it surface without running anything yourself.

Try it yourself
Loading playground...

What to remember

  • TypeScript is installed per-project (npm install --save-dev typescript); tsc --init scaffolds a tsconfig.json.
  • include tells the compiler which files belong to the project.
  • tsc can both check types and emit JavaScript, but many projects split those jobs across a fast transpiler (for output) and tsc --noEmit (for checking).
  • Most day-to-day type errors are surfaced live by your editor's language service, not by running a command.

Check yourself

4 questions · pass 3/4 to unlock Basic Types and Inference

up to 50
  1. 1.What does running tsc --init do?

  2. 2.What does the tsconfig target option control?

  3. 3.If a project only ever type-checks and never runs tsc to emit files (a bundler like esbuild or swc does the actual compiling), what is tsc typically used for?

  4. 4.Where do .ts file type errors show up during everyday editing?

4 left to answer