TypeScript Advanced Patterns yang Wajib Dikuasai di 2026
— Typescript, Programming, Best Practices — 3 min read
TypeScript Advanced Patterns yang Wajib Dikuasai di 2026 – Pengalaman Produksi Saya
Halo teman-teman,
Setelah sekian lama bermain-main dengan TypeScript, tahun ini saya semakin yakin bahwa TypeScript bukan lagi sekadar typed JavaScript, melainkan bahasa yang powerful untuk membangun sistem besar yang maintainable.
Di postingan kali ini saya akan membahas beberapa advanced pattern yang paling sering saya pakai di project production.
1. Branded Types + Template Literal Types
Salah satu fitur favorit saya adalah kombinasi branded types dengan template literal types.
type Brand<T, B> = T & { __brand: B };
type UserId = Brand<string, 'UserId'>;type OrderId = Brand<string, 'OrderId'>;
function getUser(id: UserId) { ... }
// Ini akan errorgetUser("ord_123" as OrderId); // Type mismatchDengan template literal types, kita bisa membuat tipe yang jauh lebih ketat:
type ApiRoute = `/api/${string}`;type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiEndpoint<M extends HttpMethod, R extends ApiRoute> = `${M} ${R}`;2. Zod + Infer untuk Type Safety End-to-End
Saya sudah sepenuhnya meninggalkan manual interface untuk API response. Kombinasi Zod + z.infer adalah game changer.
const CreateUserSchema = z.object({ name: z.string().min(2), email: z.string().email(), role: z.enum(["admin", "user", "moderator"]), metadata: z.record(z.string(), z.any()).optional(),});
export type CreateUserInput = z.infer<typeof CreateUserSchema>;export type User = CreateUserInput & { id: UserId; createdAt: Date };Semua validation, type inference, dan documentation otomatis ter-update.
3. Utility Types Custom yang Powerful
Beberapa utility types yang saya buat dan pakai hampir di setiap project:
// Buat semua property optional + nullabletype DeepPartial<T> = T extends object ? { [P in keyof T]?: DeepPartial<T[P]> } : T;
// Buat type yang hanya readonly di productiontype Mutable<T> = { -readonly [P in keyof T]: T[P] };
// Extract promise return typetype AsyncReturnType<T extends (...args: any) => Promise<any>> = Awaited< ReturnType<T>>;4. Dependency Injection dengan Class + Generics
Untuk service layer yang kompleks:
interface Repository<T> { findById(id: string): Promise<T | null>; save(entity: T): Promise<T>;}
class UserService<T extends User = User> { constructor(private repo: Repository<T>) {}
async createUser(data: CreateUserInput): Promise<T> { const validated = CreateUserSchema.parse(data); return this.repo.save(validated as T); }}5. TanStack Query + TypeScript Integration
Pattern yang paling sering saya pakai saat ini:
const userKeys = { all: ["users"] as const, byId: (id: UserId) => [...userKeys.all, id] as const,};
const useUser = (id: UserId) => useQuery({ queryKey: userKeys.byId(id), queryFn: () => api.users.getById(id), staleTime: 1000 * 60 * 5, });Kesimpulan & Saran Saya
Di tahun 2026, TypeScript sudah sangat matang. Kalau Anda ingin kode yang scalable dan maintainable:
- Kuasai Zod untuk validation
- Manfaatkan Branded Types & Template Literal Types
- Buat utility types sendiri
- Gunakan Domain-Driven Design lite (Value Object, Entity, Service)
- Selalu prioritaskan Developer Experience (DX)
TypeScript bukan tentang mengetik lebih banyak kode, tapi tentang menulis kode yang lebih sedikit tapi jauh lebih aman.
Apa pendapat kalian?
Pattern TypeScript mana yang paling sering kalian pakai di production? Atau ada topik teknikal lain yang ingin saya bahas di postingan berikutnya (misalnya: Next.js App Router advanced, Database design, Testing strategy, dll)?
Ceritakan di komentar!
— Ady Rahmansyah
Software Engineer | Tech Blogger | Coffee Addict