TypeScript for Beginners: Types, Interfaces, Generics, tsconfig, Migrating From JavaScript and Common Patterns
Learn TypeScript step by step: why use it, installing, basic types, interfaces and type aliases, unions, generics, functions, classes, tsconfig settings, working with the DOM and migrating a JavaScript project safely.
TypeScript is JavaScript with a type system. You describe the shape of your data, and the compiler catches many mistakes before the code runs. It is now standard in larger React, Angular and Node projects, and it is often listed in job descriptions. This guide teaches the core ideas with examples.
Why TypeScript?
- Catches typos and wrong argument types at compile time.
- Gives better autocomplete and refactoring in editors.
- Documents what functions expect and return.
- Scales better in large teams.
It compiles to plain JavaScript, so it runs anywhere JavaScript does. Make sure you know JavaScript basics first.
Install and run
npm install -D typescript
npx tsc --init
npx tsc # compile
node dist/app.js # run output
You can also run TypeScript files directly with tools such as tsx or ts-node, or newer Node versions that can strip types. tsc --init creates tsconfig.json.
Basic types
let name: string = "Asha";
let age: number = 25;
let active: boolean = true;
let tags: string[] = ["a", "b"];
let pair: [string, number] = ["age", 25]; // tuple
let anything: unknown = JSON.parse("{}"); // safer than any
Often you can skip annotations, since TypeScript infers types from values. Avoid any where possible, because it switches off checking. Use unknown and narrow it.
Functions
function gst(amount: number, rate: number = 18): number {
return Math.round(amount * rate) / 100;
}
const greet = (name: string, title?: string): string =>
title ? `${title} ${name}` : name;
Parameters and return values can be typed. A question mark makes a parameter optional.
Interfaces and type aliases
interface User {
id: number;
name: string;
email?: string;
readonly createdAt: Date;
}
type Role = "admin" | "editor" | "viewer";
type Account = {
user: User;
role: Role;
};
const acc: Account = {
user: { id: 1, name: "Ravi", createdAt: new Date() },
role: "editor",
};
Both describe object shapes. Interfaces can be extended and merged, and type aliases can describe unions, tuples and more. In practice, pick one style and stay consistent.
Unions and narrowing
function show(value: string | number) {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toFixed(2);
}
type Shape =
| { kind: "circle"; r: number }
| { kind: "rect"; w: number; h: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.r ** 2;
case "rect": return s.w * s.h;
}
}
Discriminated unions, with a shared kind field, let the compiler check that you handled every case.
Generics
function first<T>(items: T[]): T | undefined {
return items[0];
}
interface ApiResponse<T> {
data: T;
error?: string;
}
const r: ApiResponse<User[]> = { data: [] };
Generics let you write reusable code that keeps type information. Useful built-in helpers include Partial<T>, Pick<T, K>, Omit<T, K> and Record<K, V>.
Classes
class Counter {
private count = 0;
increment(): number { return ++this.count; }
}
Recommended tsconfig settings
"strict": trueturns on the full set of safety checks."target"and"module"set output style."outDir": "dist"and"rootDir": "src"keep output tidy."noUncheckedIndexedAccess"adds extra safety for arrays.
Working with the DOM and libraries
const input = document.querySelector<HTMLInputElement>("#email");
input?.addEventListener("input", () => console.log(input.value));
Install type definitions for libraries that do not ship them, for example npm i -D @types/node. Most modern libraries bundle their own types. See Node.js and React hooks, both easy to use with TypeScript.
Migrating from JavaScript
- Add TypeScript and a tsconfig with
allowJs: true. - Rename files from .js to .ts one at a time.
- Start with loose settings, then enable
strict. - Replace
anygradually with real types. - Add the compiler check to your continuous integration.
Common mistakes
- Using
anyeverywhere. - Using type assertions (
as) to silence errors rather than fixing them. - Forgetting that types vanish at runtime, so validate external data (API, forms) with a library like zod.
- Over-engineering complex types.
A short practice routine
Take a small JavaScript script you have written, such as a to-do app or an EMI calculator, and convert it to TypeScript. Turn on strict mode, fix each error, and write interfaces for your data. Notice how many bugs the compiler finds, such as a function that sometimes returns undefined or an object missing a field. Then build a typed wrapper for an API call so that the response shape is known throughout the app. After two or three conversions the type system becomes natural. Learn utility types gradually, and avoid writing clever types that nobody on the team can read. Clear, simple types that document your data are worth more than complex ones.
Frequently asked questions
What is TypeScript?
A typed superset of JavaScript that compiles to plain JavaScript.
Do I need to learn JavaScript first?
Yes, TypeScript builds on JavaScript knowledge.
Interface or type?
Both work for object shapes, choose one style and stay consistent.
What does strict mode do?
It enables a group of stricter type checks.
Does TypeScript run in the browser?
Browsers run the compiled JavaScript output.
Is any bad?
It disables type checking, so use sparingly.
Last reviewed 8 November 2026. Rates, limits and rules change, so confirm figures with the official source before you act.
Free tools related to this article
Keep reading
Information on AMTools is for general guidance and is not professional financial, tax, legal or medical advice. Rules, rates and limits change, so check the latest official source before acting.