Fundamentals
2 min readRapid overview
TypeScript Fundamentals
Core TypeScript concepts for frontend development.
Table of Contents
- Types and Inference
- Unions and Intersections
- Interfaces vs Type Aliases
- Generics
- Narrowing and Guards
- Functions and Overloads
- Classes and Access Modifiers
- Modules and tsconfig Basics
Types and Inference
let count = 0; // number inferred
let label: string = 'Tasks';
let isOpen = false; // boolean inferred
const ids = [1, 2, 3]; // number[] inferred
const mixed: (string | number)[] = [1, 'two'];
Use explicit annotations when inference is unclear or when defining public APIs.
Unions and Intersections
type Id = string | number;
function formatId(id: Id) {
return typeof id === 'number' ? id.toFixed(0) : id.toUpperCase();
}
type WithTimestamp = { createdAt: string };
type WithAuthor = { author: string };
type AuditRecord = WithTimestamp & WithAuthor;
Unions represent alternatives, intersections combine required fields.
Interfaces vs Type Aliases
interface User {
id: string;
name: string;
}
interface Admin extends User {
role: 'admin';
}
type Status = 'idle' | 'loading' | 'success' | 'error';
type ApiResponse = {
status: Status;
data?: unknown;
};
Use interfaces for object shapes you expect to extend, and type aliases for unions, primitives, and composable helpers.
Generics
function identity<T>(value: T): T {
return value;
}
const name = identity('Ada');
const countValue = identity(42);
function mapValues<T, U>(items: T[], mapper: (item: T) => U): U[] {
return items.map(mapper);
}
Add constraints to keep generics safe:
function toMap<T extends { id: string }>(items: T[]) {
return new Map(items.map((item) => [item.id, item]));
}
Narrowing and Guards
type Result = { ok: true; value: string } | { ok: false; error: string };
function handleResult(result: Result) {
if (result.ok) {
return result.value;
}
return result.error;
}
function isString(value: unknown): value is string {
return typeof value === 'string';
}
Use typeof, instanceof, in, and custom predicates to narrow types safely.
Functions and Overloads
function parseInput(input: string): number;
function parseInput(input: number): number;
function parseInput(input: string | number): number {
return typeof input === 'string' ? Number(input) : input;
}
const fromString = parseInput('42');
const fromNumber = parseInput(42);
Overloads let you expose precise call signatures while implementing a single function body.
Classes and Access Modifiers
class Session {
public readonly id: string;
private token: string;
constructor(id: string, token: string) {
this.id = id;
this.token = token;
}
refresh(newToken: string) {
this.token = newToken;
}
}
Use public, private, and protected to communicate intent and enforce encapsulation.
Modules and tsconfig Basics
export function toTitleCase(value: string) {
return value.replace(/\b\w/g, (char) => char.toUpperCase());
}
import { toTitleCase } from './strings';
Common tsconfig.json settings for frontend apps:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"noImplicitAny": true
}
}