Salvo

WFN Üye
Konular
1,725
Mesajlar
1,747
Çözüm
0
Ticaret Puanı
0
Üyelik
6 Ay 16 Gün
Konum
İstanbul
Web Sitesi
Yok
Alanı
Belirtmemiş
1/1
Konu sahibi
İki seçenekten birini her durumda üstün kabul etmek yerine şu pratik kuralı kullanın: Bir nesnenin özelliklerini ve genişletilebilir bir sözleşmeyi tanımlıyorsanız interface, birleşim, demet, ilkel tür veya koşullu tür gibi daha geniş bir tür ifadesine ihtiyacınız varsa type kullanın. Kararsız kaldığınızda interface ile başlamak genellikle uygundur; kullandığınız yapı interface ile ifade edilemiyorsa type seçin. Bu tercih çalışma zamanındaki JavaScript çıktısını değiştirmez, yalnızca TypeScript’in derleme aşamasındaki tür denetimini ve kodun nasıl genişletileceğini etkiler.

Aynı nesne için iki yazım da mümkün olabilir​


interface, çoğunlukla bir nesnenin sahip olması gereken özellikleri adlandırılmış bir sözleşme olarak tanımlar. type ise bir tür için yeni bir ad oluşturur. Basit bir nesne söz konusu olduğunda aşağıdaki iki tanım benzer biçimde kullanılabilir:

Kod:
interface User {
  id: number;
  name: string;
}

type User = {
  id: number;
  name: string;
};

Her iki tanım da id alanı sayı, name alanı dize olan bir nesneyi kabul eder. Örneğin const user: User = { id: 1, name: "Ayşe" }; ifadesi, ilgili tanım kullanıldığında geçerlidir. Eksik veya yanlış türde bir alan verilirse TypeScript hata bildirir.

Burada önemli nokta, iki yazımın da JavaScript’e interface veya type adıyla bir nesne üretmemesidir. Bunlar çalışma zamanında var olan sınıflar ya da doğrulama mekanizmaları değildir. Derleme sırasında tür kontrolü sağlarlar; dışarıdan gelen JSON verisinin gerçekten bu yapıya sahip olduğunu kendiliğinden kanıtlamazlar. API yanıtı gibi güvenilmeyen veriler için ayrıca çalışma zamanı doğrulaması gerekir.

Nesne sözleşmelerinde neden interface tercih edilir?​


Bir model, seçenek nesnesi, sınıfın uygulaması gereken sözleşme veya kütüphane tarafından dışarı açılan nesne yapısı tanımlıyorsanız interface daha anlaşılır bir başlangıçtır:

Kod:
interface Product {
  id: number;
  title: string;
  price: number;
}

interface DiscountedProduct extends Product {
  discountRate: number;
}

Burada DiscountedProduct, Product içindeki alanları devralır ve kendi alanını ekler. Bu kullanım, modelin temel yapısı ile ondan türeyen yapı arasındaki ilişkiyi doğrudan gösterir. Bir interface birden fazla interface’i de genişletebilir.

interface ayrıca aynı ada sahip bildirimlerin birleştirilebilmesine izin verir. Bu davranışa declaration merging, yani bildirim birleştirme denir:

Kod:
interface AppConfig {
  apiUrl: string;
}

interface AppConfig {
  timeout: number;
}

const config: AppConfig = {
  apiUrl: "/api",
  timeout: 5000,
};

İki AppConfig bildirimi tek bir yapı gibi değerlendirilir. Bu özellik, özellikle kütüphane türlerini genişletmek veya global nesnelere TypeScript türü eklemek gerektiğinde kullanılabilir. Ancak uygulama kodunda aynı adı farklı dosyalarda farkında olmadan yeniden tanımlamak kafa karışıklığına yol açabileceği için bildirim birleştirmeyi yalnızca bilinçli bir tasarım kararı olduğunda kullanın.

type hangi durumlarda doğru seçimdir?​


type, tek başına bir nesne yapısından daha fazlasını adlandırabilir. Birleşim türü, demet, ilkel tür için takma ad, fonksiyon türü veya koşullu tür yazmanız gerektiğinde genellikle type kullanılır.

Kod:
type Status = "pending" | "success" | "error";

type Point = [x: number, y: number];

type Identifier = string | number;

type Handler = (message: string) => void;

Bu örnekte Status yalnızca üç belirli dizeden birini, Point iki elemanlı bir demeti, Identifier dize veya sayıyı, Handler ise belirli imzaya sahip bir fonksiyonu ifade eder. Bu yapıların tamamını interface ile aynı açıklıkta tanımlayamazsınız; özellikle birleşim ve demet türlerinde type gerekli hale gelir.

type, nesne türlerini birleştirmek için kesişim türlerini de kullanır:

Kod:
type HasId = {
  id: number;
};

type HasTimestamps = {
  createdAt: Date;
  updatedAt: Date;
};

type StoredEntity = HasId & HasTimestamps;

StoredEntity değerinin her iki yapının alanlarını da taşıması gerekir. Aynı amaç interface extends ile de ifade edilebiliyorsa iki yaklaşımın anlamı tamamen aynı değildir. Interface’lerde çakışan özellikler uyumsuzsa tanım sırasında hata alınır. Kesişim türlerinde ise aynı ada sahip farklı türler birlikte istenebilir ve sonuç kullanılamaz bir tür hâline gelebilir. Bu nedenle iki yapıyı nesne sözleşmesi olarak bilinçli biçimde genişletiyorsanız extends, tür ifadelerini birleştirmeniz gerekiyorsa & kullanın.

Aşağıdaki tablo seçim ölçütünü kısa biçimde ayırır.
İhtiyaçTercihNeden
Nesne özelliklerini adlandırmakinterfaceNesne sözleşmesini açıkça ifade eder ve genişletilebilir.
Birleşim türü yazmaktypeA | B biçimini doğrudan destekler.
Demet tanımlamaktypeEleman sırasını ve türlerini adlandırabilir.
İlkel tür için takma ad oluşturmaktypestring, number veya benzeri türleri adlandırabilir.
Fonksiyon türü tanımlamakGenellikle typeFonksiyon imzasını kısa ve doğrudan ifade eder.
Bir yapının sonradan bildirimle genişletilmesiinterfaceDeclaration merging kullanılabilir.
Sınıfın uygulaması gereken nesne sözleşmesiinterfaceimplements ile sınıfın beklenen üyeleri denetlenebilir.
Tablo mutlak bir zorunluluk listesi değildir. Bazı nesne türleri hem interface hem type ile yazılabilir. Bu durumda ekipte kullanılan kodlama kuralı, türün ileride genişletilip genişletilmeyeceği ve tanımın okuyucuya en açık biçimi belirleyici olmalıdır.

extends ile kesişim türü arasındaki farkı kontrol edin​


Aynı nesne biçimini iki farklı yolla genişletmek mümkün olsa da çakışmaların ele alınma biçimi farklıdır:

Kod:
interface User {
  id: number;
}

interface Admin extends User {
  permissions: string[];
}

// Eşdeğer amaç için type yaklaşımı

type UserByType = {
  id: number;
};

type AdminByType = UserByType & {
  permissions: string[];
};

Bu iki örnekte de yönetici nesnesi id ve permissions alanlarını taşır. Ancak temel türlerde aynı özellik farklı türlerle tanımlanırsa interface bildirimi uyumsuzluğu erken bildirir. Kesişim türü ise iki koşulu aynı anda karşılamaya çalışır. Örneğin string & number pratikte hiçbir normal değerin sağlayamayacağı bir türdür. Bu nedenle çakışmayı derleme sırasında daha görünür kılmak istediğiniz nesne hiyerarşilerinde interface extends daha güvenli ve okunabilir olabilir.

Günlük kullanım için uygulanabilir karar kuralı​


Yeni bir tür tanımlarken şu sırayı izleyin:
  1. Tanımladığınız şey bir nesnenin özellikleri, bir API sözleşmesi veya bir sınıfın uygulayacağı yapıysa önce interface yazın.
  2. Tür bir birleşim (A | B), demet, ilkel tür takma adı, fonksiyon imzası veya koşullu tür içeriyorsa type kullanın.
  3. Bir nesne sözleşmesini başka nesne sözleşmeleriyle açıkça genişletiyorsanız interface extends seçin.
  4. Aynı nesne türlerini bir ifade içinde birleştirmeniz gerekiyorsa type ve & kullanın.
  5. Kütüphane veya global türleri sonradan genişletme ihtiyacı varsa declaration merging gerekip gerekmediğini kontrol edin; gerekiyorsa interface seçin.
  6. Tanım hem interface hem type ile yazılabiliyorsa, ekibin mevcut kuralını ve okuma kolaylığını koruyun; yalnızca biçimsel bir üstünlük aramayın.
Örneğin bir kullanıcı modelini ve kullanıcı durumunu birlikte tanımlamak için iki farklı yapıyı ayırabilirsiniz:

Kod:
interface User {
  id: number;
  name: string;
}

type UserState = "active" | "blocked" | "pending";

type UserRecord = User & {
  state: UserState;
};

Burada User nesnenin temel sözleşmesidir. UserState, yalnızca izin verilen durumları sınırlar. UserRecord ise iki türü birleştirir. Sonuç olarak UserRecord kullanılırken id, name ve state zorunludur; state alanı da belirtilen üç değerden biri olmalıdır. Bu ayrım, her şeyi tek bir büyük interface içine koymaktan daha anlaşılırdır çünkü nesne yapısı ile değer kümesini farklı amaçlarla ifade eder.

Sık sorulan sorular​

interface type’tan daha hızlı mıdır?​

Bazı interface genişletme biçimleri, kesişim türleriyle kurulan eşdeğer yapılara göre derleyici açısından daha uygun olabilir; ancak küçük bir projede yalnızca bu gerekçeyle tüm type tanımlarını değiştirmek doğru değildir. Önceliği türün anlamına, okunabilirliğine ve proje kuralına verin. Gerçek bir derleme sorunu varsa proje kodu ve TypeScript sürümü birlikte incelenmelidir.

Bir sınıf için interface mi type mı kullanılmalı?​

Sınıfın uygulaması gereken herkese açık üyeleri bir sözleşme olarak tanımlıyorsanız interface doğal seçimdir ve sınıf bunu implements ile uygulayabilir. Sözleşme bir birleşim, koşullu tür veya başka bir tür ifadesi içeriyorsa type kullanılabilir; ancak sınıfın implements ifadesinin gerçekten beklediğiniz yapıyı kabul ettiğini derleyiciyle kontrol etmelisiniz.

interface ile bir union type yazılabilir mi?​

Hayır. interface doğrudan "draft" | "published" gibi bir birleşim türünü tanımlamak için kullanılmaz. Bu durumda type Status = "draft" | "published"; yazmalısınız. Birleşim üyelerinin her biri nesne ise bu nesneleri interface olarak tanımlayıp sonrasında type Result = Success | Failure; biçiminde birleştirebilirsiniz.

API’den gelen veriye interface yazmak veriyi doğrular mı?​

Hayır. interface ve type yalnızca TypeScript’in derleme zamanı tür denetimidir; sunucudan gelen JSON’un gerçekten bu yapıya sahip olup olmadığını çalışma zamanında kontrol etmez. Dış veriyi kullanmadan önce alanların varlığını, türünü ve izin verilen değerlerini ayrıca doğrulamanız gerekir.
 

Sende şimdi bize katılmak ister misin?

Kayıt ol

Bize katılım kolay ve ücretsizdir!

Foruma git ?

Bu konuyu görüntüleyen kullanıcılar

Bu konuyu şu anda görüntüleyen üye bulunmuyor.
Robotlar:
  • Anthropic