ProgramlamaTypeScript mimarı

TypeScript'te yapısal (yapısal) ve nominal türleme arasındaki fark nedir? Nominal türlemeyi uygulamak mümkün mü, mümkünse nasıl? Bu ne gibi problemleri çözebilir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

TypeScript yapısal türlemeyi (structural typing) veya "ördek türlemesi"ni kullanır. Türlerin uyumluluğu için yapı (imza) önemlidir, türün adı ya da kökeni değil.

Örnek:

interface Point2D { x: number; y: number; } interface Coord2D { x: number; y: number; } // Bu türler değiştirebilir: Point2D ve Coord2D, çünkü yapılar aynıdır. const foo: Point2D = { x: 1, y: 2 }; const bar: Coord2D = foo; // TAMAM!

Nominal türleme (nominal typing): Türlerin uyumluluğu için "isim" veya "fabrika" önemlidir, yapı önemsizdir.

TypeScript'te nominal türleme yerel olarak desteklenmez, ancak branded types kullanarak taklit edilebilir:

type USD = number & { readonly __brand: unique symbol } type EUR = number & { readonly __brand: unique symbol } let priceUSD: USD; let priceEUR: EUR; // priceUSD = priceEUR; // HATA! Farklı markalar.

Bunu neden kullanmalıyız? Örneğin, yapısal olarak aynı ama anlam olarak farklı türleri ayırt etmek için — para birimleri, userID/tokenID, fiziksel büyüklükler vb.


Aldatıcı Soru

Soru: Neden aşağıdaki kod hata vermeden derleniyor, oysa Address ve UserId mantıksal olarak farklı türler?

interface Address { value: string; } interface UserId { value: string; } let id: UserId = { value: "test" }; let addr: Address = id; // TAMAM

Cevap: Çünkü TypeScript'te yapı önemlidir, tür adı değil. Her iki tür de sadece "value: string" olan bir nesnedir.


Konuyla ilgili bilgi eksikliğinden kaynaklanan gerçek hata örnekleri


Hikaye

Proje: USD/EUR cinsinden hesaplamalar yapılan finansal sistem. Miktarlar number ile iletildi. Bir gün toplamada para birimleri karıştırıldı — yapısal türleme nedeniyle TypeScript bunu fark etmedi. Daha sonra bu tür hataları derleme aşamasında önlemek için branded types eklendi.


Hikaye

Proje: REST API geliştirmede farklı varlıkların Id'leri için nesneler kullanıldı (userId, groupId), her biri value: string alanına sahipti. Yanlışlıkla userId yerine groupId kullanıldı, ve yalnızca sunucudaki iş mantığı hatayı buldu.


Hikaye

Proje: DSL için parser kütüphanesinde aynı yapılar kullanıldı (type value = { kind: 'num'|'str', value: number|string }). Benzer yapıların kodun farklı bölümlerinde karışmasına neden oldu, bu da mantıksal hatalara yol açtı. Ayrım için yapay marka alanları eklendi.