TypeScript ile uçtan uca tip güvenliği: API'den arayüze
Tip sözleşmesini backend API'den frontend arayüzüne kırılmadan taşımak ve bu süreçteki pratik yöntemler.
TypeScript, frontend projeye eklenen bir şeydir genellikle. Backend ayrı bir yerde — PHP, Go, Node — kendi tür sisteminde yazılıyor. Frontend ise TypeScript ile geliştiriliyor ama API yanıtlarına any yazılıyor, çünkü backend’in döndürdüğü yapıyı yeniden tanımlamak zahmetli.
Sonuç: iki tarafta da tip sistemi var ama aralarında bir köprü yok. Backend modeli değiştiğinde frontend derleniyor, çalışıyor, ama çalışma zamanında patlıyor. Tip sistemi burada işe yaramıyor.
End-to-end type safety bu köprüyü kurmakla ilgili.
Sorunun kökü: API sınırı
Frontend bir API çağrısı yaptığında sonuç genellikle any veya zayıf bir tip ile karşılanıyor. Şöyle:
// Zayıf tip — API değişirse TypeScript sessiz kalır
const response = await fetch('/api/orders');
const data: any = await response.json();
console.log(data.items); // items yoksa çalışma zamanında hata
Tipi elle tanımlasanız bile problem devam ediyor:
interface Order {
id: number;
status: string;
total: number;
}
const response = await fetch('/api/orders');
const data: Order[] = await response.json();
Bu sadece bir iddia. TypeScript derleme zamanında bu inanıyor; ama API gerçekte farklı bir yapı döndürürse derleme hatası almayacaksınız.
Ortak tip paketleri yaklaşımı
Monorepo veya yakın bir proje yapısında en temiz çözüm ortak tip tanımlarını paylaşmak. Tipler ayrı bir pakette yaşıyor, hem backend hem frontend bu paketten import ediyor.
Node.js tabanlı bir backend için bu doğal çalışıyor. PHP veya başka bir dil kullandığınızda ise ya API sözleşmesinden otomatik üretmek gerekiyor ya da manuel senkronizasyon.
// packages/types/src/order.ts
export interface Order {
id: number;
status: 'pending' | 'completed' | 'cancelled';
items: OrderItem[];
total: number;
createdAt: string;
}
export interface OrderItem {
productId: number;
name: string;
quantity: number;
unitPrice: number;
}
Bu paketi hem API katmanı hem de arayüz katmanı kullanıyor. Bir alan değiştiğinde her iki taraftaki kullanım yerleri derleme hatası veriyor.
OpenAPI’dan tip üretmek
Backend PHP veya Go ile yazıldığında ortak paket doğrudan çalışmıyor. Ama OpenAPI spesifikasyonunuz varsa buradan TypeScript tipleri üretmek mümkün.
openapi-typescript gibi araçlar spesifikasyon dosyasını okuyup TypeScript tanımları üretiyor:
npx openapi-typescript ./openapi.yaml --output ./src/types/api.ts
Üretilen dosyayı elle düzenlemiyorsunuz — her sürümde yeniden üretiyorsunuz. Bu yaklaşım build pipeline’a dahil edilebiliyor; backend sözleşmesi değiştiğinde frontend tipleri otomatik güncelleniyor.
Çalışma zamanı doğrulama: Zod
TypeScript tipleri derleme zamanında çalışıyor; runtime’da bir güvence vermiyor. API’den gelen veriyi gerçekten doğrulamak için runtime validation gerekiyor.
Zod bu iş için yaygın kullanılan bir kütüphane. Şema tanımlıyorsunuz, veriyi parse ediyorsunuz, hatalı veri exception fırlatıyor:
import { z } from 'zod';
const OrderSchema = z.object({
id: z.number(),
status: z.enum(['pending', 'completed', 'cancelled']),
total: z.number().positive(),
createdAt: z.string(),
});
type Order = z.infer<typeof OrderSchema>;
async function fetchOrder(id: number): Promise<Order> {
const response = await fetch(`/api/orders/${id}`);
const raw = await response.json();
return OrderSchema.parse(raw); // Hatalıysa ZodError fırlatır
}
z.infer<typeof OrderSchema> ile tip tanımı otomatik türetiliyor — şemayı ayrıca interface olarak yazmak gerekmiyor. Şema ve tip her zaman senkron.
Katmanlar arası tip sözleşmesi kırılınca ne oluyor
Bu yapıyı kurduğunuzda tip sözleşmesi kırıldığında ne oluyor: derleme hatası, test hatası veya parse hatası — bunlardan biri çalışma zamanından önce devreye giriyor.
Backend total alanını number yerine string döndürmeye başladıysa Zod parse anında hata fırlatıyor ve bu hata loglanıyor. Elle yazılmış interface Order ile bu sizi çalışma zamanı patlıyor.
Fark şu: önceki durumda kullanıcı bir şeyin bozulduğunu görüyor, sonraki durumda geliştirici bir şeyin bozulduğunu görüyor — ve neden bozulduğu açık.
Ne kadar yatırım yapmalı
Uçtan uca tip güvenliği bir spektrum. Her şeyi tam olarak bağlamak büyük bir yatırım; hiçbir şeyi bağlamamak ise ciddi bir bakım yükü.
Orta yol çoğu proje için yeterli: kritik API uçları için Zod doğrulaması, OpenAPI şeması varsa tip üretimi, ortak tipler için ayrı bir tanım dosyası. Bu üçü bir arada uygulandığında API sınırındaki sürprizlerin büyük kısmı ortadan kalkıyor.
Her şeyin mükemmel bağlı olması gerekmez. Sözleşmenin nerede olduğunu bilmek, nerede kırılabileceğini bilmek, ve kritik noktalarda doğrulama yapmak — bu yeterli başlangıç.