Typescript: tuple indeksinin türünü beyan etmek?
Bir TypeScript Demeti verildiğinde, örneğin:
const arr = [1, 2] as const;
İndeksleme üzerinde statik tür kontrolleri alıyoruz:
console.log(arr[1]);
iyi, ama
console.log(arr[2]);
hatalar ile:
Uzunluğu '2' olan 'readonly [1, 2]' demet tipinde '2' indeksinde öğe yok. ts (2493)
bu harika.
Bir sabiti, o demetin indeksinin türünde olarak tanımlamak istiyorum, böylece o sabite atanabilecek değer aynı kısıtlamalara uyar (0 | 1).
Bunu denedim:
const index: keyof typeof arr = 2 as const;
console.log(arr[index]);
ama TypeScript herhangi bir hata göstermedi. index'in çok geniş bir number olduğunu düşünüyorum.
Cevap #1
Evet, herhangi bir nedenle, demet (tuple) indeksleri, karşılık gelen sayısal literal tipleri olan 0 ve 1 yerine "0" ve "1" gibi sayısal string literal tiplerdir. Ayrıca bir number indeks imzası da vardır, bu yüzden keyof ["a", "b"] size number | "0" | "1" | ... verir. Bu da sadece keyof kullanmanın herhangi bir sayıyı atamanıza izin vereceği anlamına gelir.
Sayısal literalleri hesaplamak istiyorsanız, en az TypeScript 4.8 ve üstü sürümlerde bunu yapmak için şablon literal türlerini kullanabilirsiniz:
type TupleIndices<T extends readonly any[]> =
Extract<keyof T, `${number}`> extends `${infer N extends number}` ? N : never;
Önce tam anahtar kümesinden sayısal dize sabiti türlerini `$ {number}` üzerinde filtreleyerek Extract ile çıkarıyorum; bu, sayıya dönüştürülebilen tüm dize kümesini içeriyor. Bu, number türünü (ki bu bir dize değil) ve ayrıca "length", "slice" ve diğer dizi üyelerini elemiş oluyor. Böylece bize "0" | "1" | "2" | ... kalıyor. Daha sonra TypeScript 4.8 ile tanıtılan geliştirilmiş infer türlerini kullanarak bu dize sabitlerini sayısal sabitlere dönüştürüyorum.
Bu size şunu verir:
const arr = [1, 2] as const;
type ArrIndices = TupleIndices<typeof arr>;
// type ArrIndices = 0 | 1
type Also = TupleIndices<[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]>;
// type Also = 0 | 1 | 2 | 9 | 3 | 4 | 5 | 6 | 7 | 8
Koda yönelik oyun alanı bağlantısı
