TypeScript - Modern Type-Safe JavaScript Explained
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript, catching errors at compile-time and improving developer experience.
From interfaces and generics to advanced utility types, TypeScript scales from small scripts to large enterprise applications.
This tutorial covers essential TypeScript features with practical examples for building robust, maintainable applications.
Basic Types and Interfaces
TypeScript provides primitive types, object types via interfaces, and type aliases for reusable type definitions.
type ID = string | number;
interface User {
id: ID;
name: string;
email: string;
isActive: boolean;
role?: string; // Optional
}
const user: User = {
id: 1,
name: 'Alice',
email: 'alice@example.com',
isActive: true
};
// Readonly interface
interface Point {
readonly x: number;
readonly y: number;
}
const point: Point = { x: 10, y: 20 };
// point.x = 5; // Error!
Use interfaces for object shapes and type aliases for primitives, unions, and complex types.
Union and Intersection Types
Union types (|) allow a value to be one of several types. Intersection types (&) combine multiple types into one.
// Union types
type Status = 'loading' | 'success' | 'error';
function setStatus(status: Status) {
// TypeScript knows possible values
}
// Intersection types
type Admin = User & { permissions: string[] };
const admin: Admin = {
...user,
permissions: ['read', 'write', 'delete']
};
// Discriminated unions
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; error: string };
Generics
Generics create reusable components that work with multiple types while maintaining type safety.
// Generic function
function identity<T>(value: T): T {
return value;
}
const num = identity<number>(42);
const str = identity('hello');
// Generic class
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
const numberBox = new Box<number>(100);
// Generic constraints
function getLength<T extends { length: number }>(item: T): number {
return item.length;
}
getLength('hello'); // 5
g// getLength(42); // Error!
Utility Types
TypeScript provides built-in utility types for common type transformations.
interface User {
id: number;
name: string;
email: string;
password: string;
}
// Pick and Omit
type UserInfo = Pick<User, 'id' | 'name' | 'email'>;
type UserCredentials = Pick<User, 'email' | 'password'>;
type PublicUser = Omit<User, 'password'>;
// Partial and Required
type UpdateUser = Partial<User>;
const update: UpdateUser = { name: 'Bob' };
type RequiredUser = Required<User>;
// Record utility
type UserDict = Record<string, User>;
const users: UserDict = {
'1': user1,
'2': user2
};
Advanced Patterns
// Mapped types
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
type Partial<T> = {
[K in keyof T]?: T[K];
};
// Conditional types
type NonNullable<T> = T extends null | undefined ? never : T;
type Extract<T, U> = T extends U ? T : never;
type UserId = Extract<User['id'], string | number>; // number
// Template literal types (TS 4.1+)
type Event = `on${'Click' | 'Submit' | 'Change'}`;
const event: Event = 'onClick';
React + TypeScript
TypeScript supercharges React development with typed props, state, and hooks.
interface ButtonProps {
variant?: 'primary' | 'secondary';
onClick: () => void;
children: React.ReactNode;
disabled?: boolean;
}
function Button({ variant = 'primary', onClick, children, disabled }: ButtonProps) {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
disabled={disabled}
>
{children}
</button>
);
}
// Generic React component
function List<T>({ items, renderItem }: {
items: T[];
renderItem: (item: T) => React.ReactNode;
}) {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{renderItem(item)}</li>
))}
</ul>
);
}
tsconfig.json Essentials
- "strict": true - Enables all strict type-checking
- "noImplicitAny": true - Prevents implicit any types
- "strictNullChecks": true - Distinguishes null/undefined
- "esModuleInterop": true - Better module compatibility
- "skipLibCheck": true - Skip type checking of declaration files
- "jsx": "react-jsx" - Modern React JSX transform
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react-jsx"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Conclusion
TypeScript transforms JavaScript development by catching errors early, improving code quality, and enabling better IDE support.
Start with basic types and interfaces, then progress to generics, utility types, and advanced patterns for enterprise-scale applications.
Integrate TypeScript gradually into existing projects and gradually increase strictness for maximum benefits.
Codecrown