TypeScript Essentials
Basic Types
Type annotations
// Primitives
let name: string = "Evan";
let port: number = 8080;
let active: boolean = true;
// Arrays
let ports: number[] = [22, 80, 443];
let names: Array<string> = ["sw01", "sw02"];
// Tuple — fixed-length, typed positions
let entry: [string, number] = ["sw01", 22];
// Union types — either/or
let id: string | number = "abc-123";
id = 42; // also valid
Interfaces & Type Aliases
Define object shapes
// Interface — extendable, declaration merging
interface Host {
name: string;
ip: string;
port: number;
active?: boolean; // optional
}
// Type alias — more flexible
type HostOrIP = Host | string;
type PortRange = [number, number];
// Extending interfaces
interface NetworkDevice extends Host {
vlan: number;
model: string;
}
// Record utility type
type PortMap = Record<string, number>;
const ports: PortMap = { ssh: 22, http: 80 };
Use interface for object shapes that might be extended. Use type for unions, intersections, and mapped types.
Functions
Typed parameters and return values
function add(a: number, b: number): number {
return a + b;
}
// Optional and default parameters
function connect(host: string, port: number = 443, timeout?: number): void {
console.log(`${host}:${port}`);
}
// Function type
type Predicate = (item: Host) => boolean;
const isActive: Predicate = (h) => h.active === true;
Generics
Reusable typed components
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const n = first([1, 2, 3]); // type: number | undefined
const s = first(["a", "b"]); // type: string | undefined
// Generic constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const host: Host = { name: "sw01", ip: "10.50.1.10", port: 22 };
const name = getProperty(host, "name"); // type: string
Utility Types
Built-in type transformations
// Partial — all properties optional
function updateHost(host: Host, updates: Partial<Host>) {
return { ...host, ...updates };
}
// Required — all properties required
type StrictHost = Required<Host>;
// Pick — subset of properties
type HostSummary = Pick<Host, "name" | "ip">;
// Omit — exclude properties
type PublicHost = Omit<Host, "port">;
// Readonly — immutable
const config: Readonly<Host> = { name: "sw01", ip: "10.50.1.10", port: 22 };
// config.port = 443; // Error: readonly
// NonNullable — remove null and undefined
type Defined = NonNullable<string | null | undefined>; // string
Narrowing
Type guards refine types at runtime
function process(input: string | number) {
if (typeof input === "string") {
console.log(input.toUpperCase()); // TS knows it's string here
} else {
console.log(input.toFixed(2)); // TS knows it's number here
}
}
// Discriminated unions
type Result =
| { status: "ok"; data: Host }
| { status: "error"; message: string };
function handle(result: Result) {
switch (result.status) {
case "ok":
console.log(result.data.name); // TS narrows to ok branch
break;
case "error":
console.log(result.message); // TS narrows to error branch
break;
}
}
Discriminated unions with a shared literal property (status) are the TypeScript equivalent of Rust enums with data.
tsconfig.json Essentials
Common configuration
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"outDir": "dist",
"declaration": true,
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
"strict": true enables all strict checks. Start with it on — turning it off later is easier than adding it to a large codebase.