Right, so you’ve installed TypeScript. npm install -g typescript. Feels good, right? Like you’ve just equipped your JavaScript with a fancy new toolbox. But here’s the thing: that tsc command you now have is just the most visible part of a surprisingly sophisticated ecosystem. It’s not a single tool; it’s a whole team of specialists working behind the curtain to make you look good. Let’s meet them.

The Compiler (tsc): It’s Not What You Think

First, the star of the show, the TypeScript compiler, tsc. You run it, it takes your .ts files, and poops out .js. Simple. But its job is far more nuanced than that. Its primary mission isn’t to transpile code (convert TS to JS)—that’s actually the easiest part of its job. Its real purpose is to be a static type checker.

Think of it as a hyper-vigilant, slightly pedantic proofreader. It reads your code without running it (that’s the “static” part) and looks for contradictions between your type annotations and how you actually use your values. When it finds one, it throws a error in your terminal, preventing you from shipping a type mismatch to production. This is the core of the entire value proposition.

You can run it in a watch mode (tsc --watch) to have that proofreader look over your shoulder constantly, which is how you should probably use it 99% of the time.

# This just checks for errors, doesn't emit any JS
tsc --noEmit

# This checks for errors AND emits JS, which is the default
tsc

# Your new best friend for development
tsc --watch

The beauty is that once it’s done checking, all those types are stripped away. The emitted JavaScript is clean, readable, and doesn’t contain any TypeScript-specific runtime overhead. The type system is a development-time safety net, not a runtime crutch.

The Language Server: The Real Genius

If the compiler is the proofreader, the Language Server is the brilliant editor whispering suggestions in your ear as you type. This is arguably the part you’ll interact with most. When you get autocompletion, jump-to-definition, inline hints, and red squiggles in your editor (VS Code, WebStorm, etc.), you’re not using tsc directly. You’re using the TypeScript Language Server.

It’s a separate process that understands the entire context of your project—all your files, your tsconfig.json settings, and your node_modules—in real-time. It’s why you can hover over a function imported from some deep library and see its full type signature. It’s why “Rename Symbol” actually works reliably across an entire codebase. This is the tool that makes TypeScript feel less like a chore and more like a superpower. The compiler checks your work after you save; the Language Server helps you get it right before you even finish the line.

Type Definition Files (d.ts): Borrowing Genius

Here’s where we hit a moment of pure, unadulterated engineering pragmatism. JavaScript has a… let’s say massive… ecosystem of untyped libraries. The TypeScript team could have taken a dictatorial approach (“no types, no use!”), but they’re not idiots. Instead, they invented a way to describe the types of existing JavaScript libraries separately from the libraries themselves. Behold, the type definition file (.d.ts).

These files contain only type information—no actual implementation code. They’re like a detailed instruction manual for a piece of machinery you didn’t build. You write your code, the TypeScript Language Server reads the .d.ts file for, say, lodash, and suddenly it can tell you exactly what arguments _.map expects and what it returns.

// A simplified look inside a hypothetical `get-started.d.ts` file
declare module "cool-javascript-library" {
  export function doTheThing(config: { verbose: boolean }): string;
  export const version: string;
}

Now, when you import { doTheThing } from 'cool-javascript-library', TypeScript knows exactly what doTheThing is, thanks to this declaration.

DefinitelyTyped and @types

So who writes these manuals? Sometimes the library authors do, bundling them with the library itself (this is becoming the gold standard). But for the vast back-catalog of JS libraries, the community maintains them via a massive GitHub repository called DefinitelyTyped.

This is one of the most impressive open-source efforts I’ve ever seen. You need types for left-pad? They’ve got you covered. You install them via npm using the @types/ scope:

npm install --save-dev @types/lodash

And just like that, your editor and compiler now understand the structure of the lodash library. It’s a seamless patch on the entire npm ecosystem. The system isn’t perfect—sometimes these community-maintained definitions can fall behind a library’s latest version or contain small inaccuracies—but the fact that it works as well as it does is a minor miracle. Always try to use a library with built-in types first, but know that @types is your safety net for everything else.