Loading...
Type-safe TypeScript patterns and utility types.
Narrow types safely at runtime.
// Custom type guard
function isString(value: unknown): value is string {
return typeof value === 'string';
}
// Discriminated union guard
type Result = { ok: true; data: string } | { ok: false; error: Error };
function handleResult(result: Result) {
if (result.ok) {
console.log(result.data); // TypeScript knows it's string
} else {
console.error(result.error); // TypeScript knows it's Error
}
}A generic fetch function with full type safety.
async function fetchJSON<T>(
url: string,
options?: RequestInit
): Promise<T> {
const res = await fetch(url, {
headers: { 'Content-Type': 'application/json' },
...options,
});
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
}
return res.json() as Promise<T>;
}
// Usage — fully typed!
interface User { id: number; name: string; }
const user = await fetchJSON<User>('/api/users/1');Built-in and custom utility types for cleaner TypeScript.
// Make all properties optional
type Draft = Partial<Article>;
// Make all properties required
type Complete = Required<Draft>;
// Pick specific properties
type Preview = Pick<Article, 'title' | 'image'>;
// Omit specific properties
type Safe = Omit<User, 'password' | 'token'>;
// Record type
type StatusMap = Record<string, boolean>;
// Custom: Make specific keys optional
type PartialBy<T, K extends keyof T> =
Omit<T, K> & Partial<Pick<T, K>>;
// Custom: DeepPartial
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object
? DeepPartial<T[P]>
: T[P];
};Prevent mixing up similar types like UserId and PostId.
// Brand type helper
type Brand<T, B> = T & { __brand: B };
type UserId = Brand<string, 'UserId'>;
type PostId = Brand<string, 'PostId'>;
// Creating branded values
const userId = 'user_123' as UserId;
const postId = 'post_456' as PostId;
// Type error! Can't mix them up
function getUser(id: UserId) { /* ... */ }
getUser(postId); // TS Error!
getUser(userId); // OK