TypeScript type annotations, interfaces, generics, and utility types
string, number, boolean, null, undefined, symbol, bigint
let name: string = "Alice";
let age: number = 30;
let active: boolean = true;Typed arrays using T[] or Array<T> syntax
let nums: number[] = [1, 2, 3];
let strs: Array<string> = ["a", "b"];Fixed-length arrays with specific types per position
let pair: [string, number] = ["Alice", 30];any skips type checking; unknown is type-safe alternative
let x: unknown = getData();
if (typeof x === "string") console.log(x.toUpperCase());void for functions with no return; never for unreachable code
function log(msg: string): void { console.log(msg); }
function fail(): never { throw new Error(); }Define the shape of an object
interface User {
id: number;
name: string;
email?: string; // optional
}Inherit and extend interface definitions
interface Admin extends User {
role: string;
permissions: string[];
}Describe callable objects in interfaces
interface Transformer {
(input: string): string;
}Prevent reassignment after initialization
interface Config {
readonly apiKey: string;
timeout: number;
}Functions that work with multiple types
function identity<T>(arg: T): T { return arg; }
const result = identity<string>("hello");Interfaces parameterized by type
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}Restrict what types can be used
function getLength<T extends { length: number }>(arg: T): number {
return arg.length;
}A value can be one of several types
type StringOrNumber = string | number;
function format(val: string | number): string {
return String(val);
}Combine multiple types into one
type AdminUser = User & Admin;
const admin: AdminUser = { id: 1, name: "Bob", role: "admin", permissions: [] };Union types with a common literal field for narrowing
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };Tell TypeScript the specific type of a value
const input = document.getElementById("name") as HTMLInputElement;
const len = (someVal as string).length;Narrow types using typeof checks
function process(val: string | number) {
if (typeof val === "string") return val.toUpperCase();
return val.toFixed(2);
}Narrow types using instanceof checks
if (error instanceof TypeError) {
console.log(error.message);
}Make all properties optional or required
type PartialUser = Partial<User>; // all optional
type RequiredUser = Required<User>; // all requiredSelect or exclude specific properties
type UserPreview = Pick<User, "id" | "name">;
type WithoutEmail = Omit<User, "email">;Construct an object type with specific keys and value type
type PageMap = Record<string, string>;
const routes: Record<"home" | "about", string> = { home: "/", about: "/about" };Extract return type or parameter types from a function
type Fn = (x: number) => string;
type R = ReturnType<Fn>; // string
type P = Parameters<Fn>; // [number]Auto-incrementing numeric values
enum Direction { Up, Down, Left, Right }
const dir: Direction = Direction.Up; // 0Explicit string values for each member
enum Status {
Active = "ACTIVE",
Inactive = "INACTIVE",
Pending = "PENDING"
}Inlined at compile time for better performance
const enum HttpMethod { GET = "GET", POST = "POST", DELETE = "DELETE" }Function with typed parameters, return type, and error handling
async function fetchUser(id: number): Promise<User | null> {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) return null;
return res.json() as Promise<User>;
} catch {
return null;
}
}Reusable component with generic type parameter
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
keyExtractor: (item: T) => string;
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map((item) => (
<li key={keyExtractor(item)}>{renderItem(item)}</li>
))}
</ul>
);
}Transform object types programmatically
// Make all properties nullable
type Nullable<T> = { [K in keyof T]: T[K] | null };
// Make all values a string
type Stringified<T> = { [K in keyof T]: string };
// Make certain keys optional
type OptionalKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;Enable strict: true in tsconfig.json for maximum type safety
Prefer interface over type aliases for object shapes — they are extendable
Use unknown instead of any when the type is truly not known
Leverage utility types (Partial, Pick, Omit) instead of duplicating interface definitions
Use discriminated unions for state machines and tagged variants