Pattern 1: Type-Safe Event Emitter
```typescript
type EventMap = {
"user:created": { id: string; name: string };
"user:updated": { id: string };
"user:deleted": { id: string };
};
class TypedEventEmitter> {
private listeners: {
[K in keyof T]?: Array<(data: T[K]) => void>;
} = {};
on(event: K, callback: (data: T[K]) => void): void {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]!.push(callback);
}
emit(event: K, data: T[K]): void {
const callbacks = this.listeners[event];
if (callbacks) {
callbacks.forEach(callback => callback(data));
}
}
}
const emitter = new TypedEventEmitter();
emitter.on("user:created", (data) => {
console.log(data.id, data.name); // Type-safe!
});
emitter.emit("user:created", { id: "1", name: "John" });
// emitter.emit("user:created", { id: "1" }); // Error: missing 'name'
```
Pattern 2: Type-Safe API Client
```typescript
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type EndpointConfig = {
"/users": {
GET: { response: User[] };
POST: { body: { name: string; email: string }; response: User };
};
"/users/:id": {
GET: { params: { id: string }; response: User };
PUT: { params: { id: string }; body: Partial; response: User };
DELETE: { params: { id: string }; response: void };
};
};
type ExtractParams = T extends { params: infer P } ? P : never;
type ExtractBody = T extends { body: infer B } ? B : never;
type ExtractResponse = T extends { response: infer R } ? R : never;
class APIClient>> {
async request<
Path extends keyof Config,
Method extends keyof Config[Path]
>(
path: Path,
method: Method,
...[options]: ExtractParams extends never
? ExtractBody extends never
? []
: [{ body: ExtractBody }]
: [{
params: ExtractParams;
body?: ExtractBody;
}]
): Promise> {
// Implementation here
return {} as any;
}
}
const api = new APIClient();
// Type-safe API calls
const users = await api.request("/users", "GET");
// Type: User[]
const newUser = await api.request("/users", "POST", {
body: { name: "John", email: "john@example.com" }
});
// Type: User
const user = await api.request("/users/:id", "GET", {
params: { id: "123" }
});
// Type: User
```
Pattern 3: Builder Pattern with Type Safety
```typescript
type BuilderState = {
[K in keyof T]: T[K] | undefined;
};
type RequiredKeys = {
[K in keyof T]-?: {} extends Pick ? never : K;
}[keyof T];
type OptionalKeys = {
[K in keyof T]-?: {} extends Pick ? K : never;
}[keyof T];
type IsComplete =
RequiredKeys extends keyof S
? S[RequiredKeys] extends undefined
? false
: true
: false;
class Builder = {}> {
private state: S = {} as S;
set(
key: K,
value: T[K]
): Builder> {
this.state[key] = value;
return this as any;
}
build(
this: IsComplete extends true ? this : never
): T {
return this.state as T;
}
}
interface User {
id: string;
name: string;
email: string;
age?: number;
}
const builder = new Builder();
const user = builder
.set("id", "1")
.set("name", "John")
.set("email", "john@example.com")
.build(); // OK: all required fields set
// const incomplete = builder
// .set("id", "1")
// .build(); // Error: missing required fields
```
Pattern 4: Deep Readonly/Partial
```typescript
type DeepReadonly = {
readonly [P in keyof T]: T[P] extends object
? T[P] extends Function
? T[P]
: DeepReadonly
: T[P];
};
type DeepPartial = {
[P in keyof T]?: T[P] extends object
? T[P] extends Array
? Array>
: DeepPartial
: T[P];
};
interface Config {
server: {
host: string;
port: number;
ssl: {
enabled: boolean;
cert: string;
};
};
database: {
url: string;
pool: {
min: number;
max: number;
};
};
}
type ReadonlyConfig = DeepReadonly;
// All nested properties are readonly
type PartialConfig = DeepPartial;
// All nested properties are optional
```
Pattern 5: Type-Safe Form Validation
```typescript
type ValidationRule = {
validate: (value: T) => boolean;
message: string;
};
type FieldValidation = {
[K in keyof T]?: ValidationRule[];
};
type ValidationErrors = {
[K in keyof T]?: string[];
};
class FormValidator> {
constructor(private rules: FieldValidation) {}
validate(data: T): ValidationErrors | null {
const errors: ValidationErrors = {};
let hasErrors = false;
for (const key in this.rules) {
const fieldRules = this.rules[key];
const value = data[key];
if (fieldRules) {
const fieldErrors: string[] = [];
for (const rule of fieldRules) {
if (!rule.validate(value)) {
fieldErrors.push(rule.message);
}
}
if (fieldErrors.length > 0) {
errors[key] = fieldErrors;
hasErrors = true;
}
}
}
return hasErrors ? errors : null;
}
}
interface LoginForm {
email: string;
password: string;
}
const validator = new FormValidator({
email: [
{
validate: (v) => v.includes("@"),
message: "Email must contain @"
},
{
validate: (v) => v.length > 0,
message: "Email is required"
}
],
password: [
{
validate: (v) => v.length >= 8,
message: "Password must be at least 8 characters"
}
]
});
const errors = validator.validate({
email: "invalid",
password: "short"
});
// Type: { email?: string[]; password?: string[]; } | null
```
Pattern 6: Discriminated Unions
```typescript
type Success = {
status: "success";
data: T;
};
type Error = {
status: "error";
error: string;
};
type Loading = {
status: "loading";
};
type AsyncState = Success | Error | Loading;
function handleState(state: AsyncState): void {
switch (state.status) {
case "success":
console.log(state.data); // Type: T
break;
case "error":
console.log(state.error); // Type: string
break;
case "loading":
console.log("Loading...");
break;
}
}
// Type-safe state machine
type State =
| { type: "idle" }
| { type: "fetching"; requestId: string }
| { type: "success"; data: any }
| { type: "error"; error: Error };
type Event =
| { type: "FETCH"; requestId: string }
| { type: "SUCCESS"; data: any }
| { type: "ERROR"; error: Error }
| { type: "RESET" };
function reducer(state: State, event: Event): State {
switch (state.type) {
case "idle":
return event.type === "FETCH"
? { type: "fetching", requestId: event.requestId }
: state;
case "fetching":
if (event.type === "SUCCESS") {
return { type: "success", data: event.data };
}
if (event.type === "ERROR") {
return { type: "error", error: event.error };
}
return state;
case "success":
case "error":
return event.type === "RESET" ? { type: "idle" } : state;
}
}
```