javascript
Table of Contents
TypeScript
Useful TypeScript snippets and patterns.
Type Utilities
Make specific properties optional
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
interface User {
id: string;
name: string;
email: string;
}
// id is now optional
type CreateUserInput = PartialBy<User, "id">;
Extract union of object values
const STATUS = {
active: "active",
inactive: "inactive",
pending: "pending",
} as const;
type Status = (typeof STATUS)[keyof typeof STATUS];
// "active" | "inactive" | "pending"
Exhaustive switch checking
function assertNever(x: never): never {
throw new Error(`Unexpected value: ${x}`);
}
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side ** 2;
default:
return assertNever(shape); // compiler error if a case is missed
}
}
Zod (Runtime Validation)
Define a schema and infer the type
import { z } from "zod";
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1),
email: z.string().email(),
role: z.enum(["admin", "user"]),
createdAt: z.coerce.date(),
});
type User = z.infer<typeof UserSchema>;
// Parse (throws on invalid data)
const user = UserSchema.parse(untrustedData);
// Safe parse (returns result object)
const result = UserSchema.safeParse(untrustedData);
if (result.success) {
console.log(result.data);
} else {
console.error(result.error.flatten());
}
Async Patterns
Promise.allSettled with typed results
async function fetchAll<T>(urls: string[], fetcher: (url: string) => Promise<T>) {
const results = await Promise.allSettled(urls.map(fetcher));
const successes = results
.filter((r): r is PromiseFulfilledResult<T> => r.status === "fulfilled")
.map((r) => r.value);
const failures = results
.filter((r): r is PromiseRejectedResult => r.status === "rejected")
.map((r) => r.reason);
return { successes, failures };
}
Retry with exponential backoff
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries = 3,
baseDelayMs = 1000
): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxRetries) throw error;
const delay = baseDelayMs * 2 ** attempt;
await new Promise((r) => setTimeout(r, delay));
}
}
throw new Error("Unreachable");
}
Generics
Generic API response wrapper
interface ApiResponse<T> {
data: T;
meta: {
total: number;
page: number;
perPage: number;
};
}
async function fetchPaginated<T>(
url: string,
schema: z.ZodType<T>
): Promise<ApiResponse<T[]>> {
const res = await fetch(url);
const json = await res.json();
return {
data: z.array(schema).parse(json.results),
meta: json.meta,
};
}
See Also
javascript.txt · Last modified: 2026/03/27 00:51 by roger