Salvo

WFN Üye
Konular
1,745
Mesajlar
1,767
Çözüm
0
Ticaret Puanı
0
Üyelik
6 Ay 16 Gün
Konum
İstanbul
Web Sitesi
Yok
Alanı
Belirtmemiş
1/1
Konu sahibi
Union türünü daraltmak için TypeScript’in çalışma zamanında gerçekten kontrol edebildiği bir koşul kullanmalısınız. En güvenilir yöntem, seçenekleri ayıran ortak bir alan tanımlayıp bu alanı kontrol etmektir. Kontrol başarılı olduğunda TypeScript ilgili dalda hangi özelliklerin kullanılabileceğini bilir; koşul dışında ise diğer union üyelerini kullanmaya devam eder.

Ortak ayırt edici alanla daraltma​


Bir union içindeki nesneler aynı alan adına, fakat farklı sabit değerlere sahipse buna ayırt edici alanla daraltma denir. Bu alan genellikle type, kind veya status adını taşır.

Kod:
type Success = {
  type: "success";
  data: string;
};

type Failure = {
  type: "failure";
  error: string;
};

type Result = Success | Failure;

function printResult(result: Result): void {
  if (result.type === "success") {
    console.log(result.data);
    return;
  }

  console.error(result.error);
}

Burada result.type === "success" koşulu doğruysa result artık Success olarak değerlendirilir ve data alanı kullanılabilir. Koşul yanlış olduğunda geriye Failure kalır; bu nedenle error alanına erişilebilir.

Bu kontrol yalnızca çalışma zamanında gerçekten mevcut olan bir değeri sınar. TypeScript’e “bu nesne kesinlikle başarılıdır” demek, nesnenin çalışma zamanındaki içeriğini değiştirmez ve yanlış veri gelmesini engellemez. Verinin dış kaynaktan geldiği durumlarda çalışma zamanı doğrulaması yine gerekebilir.

Temel daraltma yöntemleri​


Kullanacağınız yöntem, union üyelerinin nasıl ayrıldığına bağlıdır.
KontrolUygun olduğu durumÖrnek
typeofİlkel türleri ayırmatypeof value === "string"
inNesnelerin sahip olduğu alanları ayırma"radius" in shape
instanceofSınıf örneklerini ayırmavalue instanceof Date
Eşitlik kontrolüOrtak sabit alanla ayrılan union türleri === "success"
Özel type guardTekrarlanan veya karmaşık kontrollerisSuccess(result)
Bu yöntemlerin hepsi aynı işi yapmaz. typeof ve instanceof çalışma zamanı değerlerini kontrol ederken, ayırt edici alan kontrolü nesnenin belirli bir özelliğine dayanır. Alan adını kontrol etmek için in kullanabilirsiniz:

Kod:
type Circle = {
  radius: number;
};

type Square = {
  sideLength: number;
};

type Shape = Circle | Square;

function getArea(shape: Shape): number {
  if ("radius" in shape) {
    return Math.PI * shape.radius ** 2;
  }

  return shape.sideLength ** 2;
}

"radius" in shape doğru olduğunda TypeScript nesneyi Circle olarak daraltır. Ancak alanların aynı anda bulunabileceği karmaşık modellerde yalnızca alan varlığına güvenmek yerine ayırt edici bir alan kullanmak daha açıktır.

İlkel değerlerde typeof kullanılabilir:

Kod:
function formatValue(value: string | number): string {
  if (typeof value === "string") {
    return value.trim();
  }

  return value.toFixed(2);
}

value ilk dalda string, ikinci dalda number olur. typeof ile yalnızca JavaScript’in desteklediği temel tür kontrollerini yapabilirsiniz; özel arayüz adları çalışma zamanında mevcut olmadığı için typeof value === "User" gibi bir kontrol geçerli değildir.

Özel type guard yazma​


Aynı kontrolü birden fazla yerde kullanıyorsanız, sonucu value is Type biçiminde bildirilen bir type guard işlevine taşıyabilirsiniz.

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

type ErrorResponse = {
  message: string;
};

type Response = User | ErrorResponse;

function isUser(value: Response): value is User {
  return "id" in value && "name" in value;
}

function showResponse(response: Response): string {
  if (isUser(response)) {
    return response.name;
  }

  return response.message;
}

isUser true döndürdüğünde TypeScript, çağrının yapıldığı yerde response değerini User kabul eder. Type guard içindeki koşul yanlış yazılırsa derleyici bu mantık hatasını tamamen yakalayamaz; bu nedenle işlevin döndürdüğü boolean ile bildirilen türün gerçekten eşleşmesi sizin sorumluluğunuzdadır.

Dışarıdan gelen JSON verilerinde type guard, veriyi otomatik olarak güvenilir hâle getirmez. Örneğin yalnızca id alanının bulunması, alanın gerçekten sayı olduğu anlamına gelmez. Böyle bir durumda türü ve gerekli alanların değerlerini ayrıca kontrol edin.

Union türü tamamen ele alındığında kontrol etmek​


Union üyelerinin tümünü işlediğinizden emin olmak için son dalda never kullanabilirsiniz. never, o noktaya ulaşabilecek hiçbir değer olmaması gerektiğini ifade eder.

Kod:
type Action =
  | { type: "add"; value: number }
  | { type: "remove"; value: number }
  | { type: "reset" };

function assertNever(value: never): never {
  throw new Error(`Bilinmeyen işlem: ${String(value)}`);
}

function applyAction(action: Action, total: number): number {
  switch (action.type) {
    case "add":
      return total + action.value;
    case "remove":
      return total - action.value;
    case "reset":
      return 0;
    default:
      return assertNever(action);
  }
}

Daha sonra Action union’ına yeni bir seçenek eklerseniz ve switch içine karşılığını yazmazsanız, action değeri never bekleyen işleve uymaz ve eksik dalı fark edersiniz. Bu yaklaşım çalışma zamanında bilinmeyen veriyi güvenli biçimde karşılamanın yerine geçmez; derleme aşamasında union tanımının bütün üyelerinin ele alınmasını sağlar.

Daraltma çalışmadığında kontrol edilecek noktalar​


Bir alanı kontrol ettiğiniz hâlde TypeScript türü daraltmıyorsa önce kontrolün union’ın gerçek yapısıyla örtüşüp örtüşmediğine bakın. Kontrol edilen alanın her union üyesinde bulunması, değerlerinin sabit türlerle tanımlanması ve koşulun aynı değişken üzerinde yapılması gerekir.

Örneğin aşağıdaki tanımda kind alanı genel string türündedir:

Kod:
type A = { kind: string; value: number };
type B = { kind: string; message: string };
type Item = A | B;

Bu yapı, kind alanının hangi üyeyi temsil ettiğini TypeScript’e bildirmez. Daha belirgin bir union için sabit değerler kullanın:

Kod:
type A = { kind: "value"; value: number };
type B = { kind: "message"; message: string };
type Item = A | B;

Artık item.kind === "value" kontrolü Item türünü doğru biçimde daraltır. Nesneyi as ile zorla başka bir türe çevirmek ise daraltma yapmaz; yalnızca derleyiciye bir varsayımı kabul ettirir. Bu varsayım yanlışsa çalışma zamanında hata alabilirsiniz. Önce gerçek bir kontrol, karmaşık durumlarda da doğrulama işlevi kullanın.
 

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