Soru zamanlaması:
Bazı görevlerde, bir fonksiyonun farklı veri yapıları döndürebilmesi gerekmektedir - örneğin, sabit uzunlukta bir dizi (tuple) veya birden fazla sonuç seçeneği (union type). Dinamik JavaScript'te bu yaklaşım, "sonuç veya hata" desenleri için yaygın olarak kullanılmaktadır (örneğin, [err, value]), ancak TypeScript, sonuç yapısını doğru bir şekilde anlaması için kesin tip tanımları gerektirir.
Sorun:
Açık bir dönüş türü belirtilmeden, TypeScript sonucu çok "geniş" (yani dar olmayan) bir biçime - dizi veya union - dönüştürmektedir; bu, geliştiriciyi otomatik tamamlama ve tür güvenliği avantajlarından mahrum bırakmaktadır. Fonksiyonun sonuçlarını destructure ederken, elemanların tiplerinin kesin tanımını kaybetme riski vardır.
Çözüm:
Conditional types ve overload tanımlarını kullanmak gerekmektedir; tuple için ise sonuç dizisinin türünü açıkça belirtmek ve sabit bir tuple döndüreceksek as const kullanmak önemlidir. Union sonuçları için ise, dışarıdan kodda dönen sonucun türünü doğru bir şekilde ayırabilmek için generics ve type narrowing'i birleştirmek gerekmektedir.
Kod örneği:
type Result<T> = [null, T] | [Error, null]; function parseNumber(str: string): Result<number> { const n = Number(str); return isNaN(n) ? [new Error('Geçersiz sayı'), null] : [null, n]; } const [err, value] = parseNumber('123'); if (err) console.error(err.message); else console.log(value!.toFixed(2)); // Tuple ile ve as const ile otomatik belirsiz yapılar: function getStatus(flag: boolean): [string, number] | string { return flag ? ['ok', 200] as const : 'hata'; } const r = getStatus(true); if (Array.isArray(r)) { // r: readonly [string, number] }
Anahtar özellikler:
Tuple'un union döndürdükten sonra, dizinin elemanının tipi her zaman belirli olacak mı?
Hayır, eğer fonksiyon union tuple'ları döndürüyorsa, destructuring sonrası elemanlar tüm olası varyasyonların türlerinin birleşimini temsil edecektir.
type R = [number, null] | [null, string]; const [a, b]: R = [1, null]; // a: number | null // b: null | string
As const ile tuple'ın tipini tamamen "dondurmak" mümkün mü?
Hayır, as const değerleri dondurur, ancak eğer fonksiyon dönüş türü belirtilmeden tanımlanmışsa, TypeScript türü gerektiğinden daha geniş tahmin edebilir. Dönüş türünü açıkça belirtmek daha iyidir.
function foo() { return [1, 'ok'] as const; } // foo(): readonly [1, "ok"]
Farklı döngü türleri olan overload'lar, destructuring sonrası sonuç türünün belirgin olmasını sağlar mı?
Overload'lar derleyiciye yardımcı olur, ancak eğer giriş parametresi bilinmiyorsa, sonuç tüm seçeneklerin union'u olacaktır. Doğru bir şekilde türü daraltmak için sonuç işleyicisinde type guards kullanmalısınız.
function bar(x: number): string; function bar(x: boolean): number; function bar(x: any): any { return typeof x === 'number' ? 'str' : 123; } const r = bar(Math.random() > 0.5 ? true : 1); // r: number | string
Fonksiyon ya bir dizi ya da hata döndürüyor, ancak bunu Type signature'da açıkça tanımlamıyor. Çağıran kodda, sonucun bir sayı olduğu bekleniyor ve result[1].toFixed(2) ifadesi runtime'da bir hata fırlatıyor.
Artıları:
Eksileri:
Fonksiyon, Result<T> türünde, kesin olarak tanımlanmış bir tuple döndürmekte; sonuç işleme, destructuring ve ilk elemanın (hata/null) runtime kontrolüne dayanarak yürütülmektedir. Derleyici, sonuca yalnızca başarılı bir tür daralmasından sonra başvurmanın garantisini vermektedir.
Artıları:
Eksileri: