What is TypeScript?
TypeScript is a superset of JavaScript that adds static typing. It helps catch errors early, improves IDE tooling (autocomplete, refactors), and compiles down to plain JavaScript.
// Plain JS
function add(a, b) { return a + b; }
// TypeScript
function add(a: number, b: number): number { return a + b; }Basic types
Common types: string, number, boolean, null, undefined, void, any, unknown, never.
let name: string = 'Ada';
let age: number = 30;
let isActive: boolean = true;
let value: unknown;
function fail(msg: string): never { throw new Error(msg); }Interface vs type
Both describe object shapes. Interfaces support declaration merging; types are more flexible (unions, mapped types). Prefer interface for public object contracts, type for advanced compositions.
interface User { id: number; name: string; }
type ApiResponse<T> = { data: T; error?: string };Generics
Generics let you write reusable components that work with multiple types while preserving type safety.
function identity<T>(value: T): T { return value; }
const x = identity<number>(42);
function wrap<T>(items: T[]): { count: number; items: T[] } {
return { count: items.length, items };
}Enums
Enums represent a set of named constants. Use string enums to avoid runtime surprises.
enum Role { Admin = 'ADMIN', User = 'USER' }
function canDelete(role: Role) { return role === Role.Admin; }Union vs intersection
Union (|) means one of many; intersection (&) combines multiple types into one.
type Id = string | number;
type WithTimestamps = { createdAt: Date } & { updatedAt: Date };Type narrowing
Refine unions using typeof, instanceof, in-guards, and custom predicates.
function print(id: string | number) {
if (typeof id === 'string') console.log(id.toUpperCase());
else console.log(id.toFixed(0));
}
function isDate(v: unknown): v is Date { return v instanceof Date; }Useful Utility Types
Built-ins: Partial, Required, Readonly, Pick, Omit, Record.
type User = { id: number; name: string; email?: string };
type UserUpdate = Partial<User>; // all fields optional
const byId: Record<number, User> = {};keyof and typeof
keyof creates a union of property names; typeof captures the type of a value.
const cfg = { host: 'localhost', port: 5432 };
type Cfg = typeof cfg; // { host: string; port: number }
type Keys = keyof Cfg; // 'host' | 'port'Non-null assertion and optional chaining
Prefer safe access with optional chaining (?.) and nullish coalescing (??). Avoid non-null (!) unless you are certain.
const user = { profile: { name: 'Ada' } } as const;
console.log(user.profile?.name ?? 'Anonymous');Modules and tsconfig basics
Configure tsconfig.json for module resolution, target, and strictness. Use ESM imports/exports.
// tsconfig.json (excerpt)
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"baseUrl": ".",
"paths": { "@/*": ["src/*"] }
}
}Conditional types
Define types based on conditions: T extends U ? X : Y. Useful for inferring return types and API transformations.
type IsString<T> = T extends string ? true : false;
Mapped types
Create new types by remapping keys using in and modifiers (readonly?).
type Readonly<T> = { readonly [K in keyof T]: T[K] };Discriminated unions
Unions with a common discriminant field enable exhaustive pattern matching via switch/case.
Module augmentation
Extend existing modules/interfaces in declaration files, useful for libraries and plugin ecosystems.
Decorators (experimental)
Annotate classes/methods with metadata; requires compiler options. Use cautiously due to evolving standardization.