TypeScript adds static types to JavaScript. It catches bugs at compile time that would otherwise crash at runtime, and it makes your editor dramatically smarter with autocomplete, refactoring, and inline documentation. This guide covers the essentials and links to deeper resources.
Getting started
TypeScript is a superset of JavaScript — every valid JS file is valid TS. You add types gradually. The compiler (tsc) checks your types and outputs plain JavaScript. If you’re wondering whether it’s worth the learning curve, read TypeScript vs JavaScript for an honest comparison, or What is TypeScript? for the fundamentals.
For a quick reference of all the syntax, bookmark the TypeScript cheat sheet.
Setting up TypeScript
Every TypeScript project needs a tsconfig.json. The settings that matter most:
strict: true— enables all strict type checks. Start with this on. It’s harder to add later.target— which JavaScript version to compile to (usuallyES2020or later)module— module system (ESNextfor modern projects,commonjsfor older Node.js)paths— import aliases like@/components/...
Our tsconfig builder generates a tsconfig.json based on your project type (React, Node.js, library, etc.) so you don’t have to memorize the options.
Common TypeScript errors and how to fix them
TypeScript’s error messages can be cryptic. Here are the ones you’ll encounter most:
Type assignment errors:
- Type is not assignable — the most common TS error. You’re passing a value that doesn’t match the expected type.
- Cannot assign to type — trying to assign to a
readonlyproperty or a narrowed type. - Argument is not assignable — function parameter type mismatch.
Null and undefined:
- Object is possibly undefined — accessing a property on something that might be
undefined. Use optional chaining (?.) or a null check. - Strict null checks fix — errors that appear when enabling
strictNullChecks.
Module and property errors:
- Cannot find module — TypeScript can’t resolve an import. Usually needs a type declaration file or
@types/package. - Property does not exist — accessing a property that isn’t in the type definition.
- No overload matches this call — function arguments don’t match any of the declared overloads.
TypeScript with React
TypeScript and React work well together. The key patterns:
// Component props
interface ButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary';
}
// useState with types
const [user, setUser] = useState<User | null>(null);
// Event handlers
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
For React-specific TypeScript issues, see React cannot find module types fix.
TypeScript with Node.js
For backend TypeScript, you’ll want:
npm install -D typescript @types/node tsx
Use tsx to run TypeScript files directly without a build step during development:
npx tsx src/server.ts
For production, compile with tsc and run the JavaScript output.
Validation at runtime
TypeScript types are erased at runtime — they don’t validate incoming data from APIs, forms, or databases. Use a runtime validation library:
- Zod — the most popular choice. Infers TypeScript types from schemas.
- Zod vs Yup — Zod is TypeScript-first, Yup is more established.
import { z } from 'zod';
const UserSchema = z.object({
name: z.string(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>; // TypeScript type from Zod schema
Linting and formatting
Keep your TypeScript code consistent:
- Biome vs ESLint — Biome is faster and simpler. ESLint has more plugins.
- Our ESLint config builder generates a config for TypeScript projects.
- The Prettier config builder handles formatting.
For an opinionated take on TypeScript’s limitations, read TypeScript Is Not Enough.
What to read next
If you’re just starting: read What is TypeScript? and the TypeScript cheat sheet.
If you’re debugging: find your error in the list above — each guide has the exact fix.
If you’re setting up a project: use the tsconfig builder and ESLint config builder to generate your config files.