TypeScript'te Tuple Kullanımı (Tip Çıkarımı)


Bu biraz yapay örnek verildiğinde:

['List', 'Of', 'Names']
        .map((name, index) => [name, index % 2])
        .map(([name, num]) => );

neden son satırdaki name ve num tipi string | number olarak açıkça bir dizi string ve numara olarak çıkarımsanıyor ve aranızda type inference kullanarak name'in string ve num'un sırasıyla number olmasını sağlayan bir yol bilen var mı?

Cevap #1

Bir const bildirimi kullanabilirsiniz:

['List', 'Of', 'Names']
    .map((name, index) => [name, index % 2] as const) // insert `as const` here
    .map(([name, num]) => { }); // name: string, num: number

Oyun alanı örneğine bir göz at.

Cevap #2

Dizi literal'leri için tip çıkarımı, demetleri çıkarmaz, dizileri çıkarır, yani

var foo = ["", 0]; // foo is Array<string | number> not [string, number]

Bu konuyla ilgili bir dokümantasyon bulamadım ama tuple desteği ekleyen pull request onları tanımlarken hiçbir zaman çıkarımı kullanmıyor, sanırım bu kasıtlı.

Sizin durumunuzda tür parametresini belirtebilirsiniz:

['List', 'Of', 'Names']
        .map<[string, number]>((name, index) => [name, index % 2])
        .map(([name, num]) => name + "");

2.9 ve altı çözüm

Veya bu sizin için yaygın bir sorun ise bir demet yardımcı fonksiyonu oluşturun:

function tuple<T1, T2, T3, T4, T5>(data: [T1, T2, T3, T4, T5]) : typeof data
function tuple<T1, T2, T3, T4>(data: [T1, T2, T3, T4]) : typeof data
function tuple<T1, T2, T3>(data: [T1, T2, T3]) : typeof data
function tuple<T1, T2>(data: [T1, T2]) : typeof data
function tuple(data: Array<any>){
    return data;
}

['List', 'Of', 'Names']
        .map((name, index) => tuple([name, index % 2]))
        .map(([name, num]) => name + "");

3.0 Çözüm

Orijinal cevabı paylaştığımdan beri TypeScript, rest parametreleri için tuple türlerini çıkarabilme yeteneğiyle çıkarımını geliştirdi. Detaylar için PR’ye bakın. Bu özellik sayesinde tuple fonksiyonunun daha kısa bir versiyonunu yazabiliriz :

function tuple<T extends any[]> (...data: T){
    return data;
}

['List', 'Of', 'Names']
        .map((name, index) => tuple(name, index % 2))
        .map(([name, num]) => name + "");

İlgili makaleler