Menu

TypeScript readonly: Özellikler, Readonly<T> ve Diziler

readonly değiştiricisi ve Readonly<T> utility type'ı, kodun özellikleri yeniden atamasını engeller. readonly özellikleri ve class alanlarını, Readonly<T> tipini, readonly dizileri (readonly T[] ve ReadonlyArray), ReadonlyMap ve ReadonlySet'i, readonly'nin neden sığ ve yalnızca derleme zamanına ait olduğunu ve Object.freeze ile as const karşısındaki yerini öğrenin.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

readonly, nesne oluşturulurken bir kez atanabilen ve bir daha yeniden atanamayan bir özelliği işaretler. Readonly<T> bunu bir tipin her özelliğine uygular, readonly T[] de diziler için aynısını yapar:

Son satır readonly hakkındaki en önemli gerçeği gösterir: derleyici tarafından kontrol edilir, çalışma zamanında zorlanmaz. Atama bir derleme hatasıydı (burada @ts-expect-error ile bastırıldı), ama üretilen JavaScript yine de onu çalıştırdı. Bastırma olmasaydı dosya derlenmezdi; readonly işini tam da orada yapar.

readonly Özellikler

Bir interface'te, bir tip literal'inde ya da bir class'ta özellik adının önüne readonly yazın. Özellik ilk değer alabilir ama yeniden atanamaz:

Bir class'ta readonly bir alan, bildiriminde ya da constructor içinde atanabilir, başka hiçbir yerde atanamaz. En kısa biçim bir parameter property'dir, constructor(readonly id: string) {}; alanı tek adımda bildirir ve atar. Alanları ve constructor'ları genel olarak classes sayfası ele alır.

Readonly<T>: Tüm Özellikler Bir Kerede

Readonly<T>, T tipinin her özelliğini readonly olarak işaretleyen bir utility type'tır. Uygulama durumu gibi, dolaştırdığınız ama değiştirmemeniz gereken değerler için işe yarar:

Fonksiyon imzası okuyucuya addItem fonksiyonunun eski durumu değiştirmek yerine yeni bir durum döndürdüğünü söyler ve derleyici fonksiyonu buna uymaya zorlar. Readonly<T>, { readonly [P in keyof T]: T[P] } mapped type'ı olarak tanımlanmıştır.

Readonly Diziler: readonly T[] ve ReadonlyArray<T>

readonly number[] ve ReadonlyArray<number> aynı tiptir. Değiştiren her metodu (push, pop, shift, splice, sort, reverse, fill...) kaldırırlar ve indeksle atamayı yasaklarlar. Değiştirmeyen metotlar kalır ve sıradan diziler döndürür:

Parametre olarak readonly T[] almak, çağıranlara dizilerini değiştirmeyeceğinize dair bir sözdür. İnsanların takıldığı yer diğer yöndür: readonly bir dizi, düz bir T[] alan bir fonksiyona geçirilemez, çünkü o fonksiyon onu değiştirebilir.

index.ts(7,17): error TS4104: The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.

Çözüm, hiçbir şeyi değiştirmediği için sum fonksiyonunu readonly number[] kabul edecek şekilde değiştirmektir. Bir diziyi yalnızca okuyan fonksiyonlar her zaman readonly tipi almalıdır; o zaman iki türü de kabul ederler. Fonksiyon size ait değilse bir kopya geçirin: sum([...prices]).

ReadonlyMap ve ReadonlySet

Map'lerin ve set'lerin de readonly sürümleri vardır. ReadonlyMap<K, V> içinde get, has, size, forEach ve iterator'lar vardır ama set, delete ya da clear yoktur; ReadonlySet<T> içinde add, delete ya da clear yoktur:

Bir class çoğu zaman private ve değiştirilebilir bir Map tutar ve onu ReadonlyMap olarak tiplenmiş bir getter ile dışarı açar; böylece dışarıdaki kod veriyi okuyabilir ama o referans üzerinden değiştiremez.

readonly Sığdır

readonly ve Readonly<T> yalnızca özelliğin kendisini korur, işaret ettiği nesneyi ya da diziyi değil:

DeepReadonly<T> kendini iç içe her nesne tipine uygular ve bir dizi tipi üzerindeki mapped type readonly bir dizi ürettiği için members tipi readonly string[] olur. Bu yine de tip düzeyinde bir sözdür, çalışma zamanında bir koruma değildir.

Yalnızca Derleme Zamanı: Başka Bir Referans Üzerinden Değişiklik

Readonly bir tip, tek bir referansın neler yapabileceğini kontrol eder. Aynı nesneye readonly olmadan tiplenmiş başka bir referans onu değiştirebilir ve TypeScript readonly bir tipi değiştirilebilir bir tipe atamaya bile izin verir:

mutable = settings ataması derlenir, çünkü TypeScript iki nesne tipinin uyumlu olup olmadığını kontrol ederken readonly özellikleri hesaba katmaz; TypeScript handbook bunu doğrudan belirtir ve bu yüzden readonly özelliklerin aliasing yoluyla değişebileceğini not eder. Readonly diziler farklıdır: yukarıdaki TS4104 hatası tam olarak bu kontroldür. Object.freeze ise çalışma zamanında değişiklikleri gerçekten engeller: üretilen kod strict mode'da çalışır ve orada dondurulmuş bir özelliğe yazmak bir TypeError fırlatır. readonly gibi Object.freeze de sığdır.

readonly, const, as const ve Object.freeze

Bir literal üzerindeki as const her özelliği her derinlikte readonly yapar ve literal tipleri korur; derinlemesine readonly bir değer elde etmenin çoğu zaman en kolay yolu budur:

const theme = { mode: "dark", sizes: [12, 14] } as const;
// { readonly mode: "dark"; readonly sizes: readonly [12, 14] }
Uygulandığı yerDerin mi?Çalışma zamanı etkisiÖrnek
constbir değişken bağlamasıhayırdeğişken yeniden atanamazconst user = {...}
readonlytek bir özellik ya da dizi tipihayıryokreadonly id: string
Readonly<T>bir tipin her özelliğihayıryokReadonly<State>
as constbir literal ifadesievetyok{ ... } as const
Object.freezebir nesne değerihayıryazmalar başarısız olur (strict mode'da hata fırlatır)Object.freeze(obj)

const ve readonly farklı sorulara cevap verir: const adın başka bir yeri göstermesini engeller, readonly bir özelliğin değişmesini engeller. Bir const nesnenin özellikleri, readonly olmadıkça yine yeniden atanabilir.

Sıkça Sorulan Sorular

TypeScript'te readonly ne işe yarar?

readonly, nesne oluşturulurken (ya da bir class constructor'ında) atanabilen ama sonrasında yeniden atanamayan bir özelliği işaretler. Sonradan ona atama yapmak bir derleme hatasıdır, TS2540. Yalnızca bir tip kontrolüdür: üretilen JavaScript hiçbir koruma içermez.

TypeScript'te readonly ile const arasındaki fark nedir?

const bir değişkenle ilgilidir: ad başka bir değere yönlendirilemez, ama tuttuğu nesne yine değiştirilebilir. readonly bir özellikle ilgilidir: o özellik yeniden atanamaz. const user = { name: "Ada" } hâlâ user.name = "x" atamasına izin verir; readonly name özelliği ise vermez.

TypeScript'te bir diziyi nasıl readonly yaparım?

Onu readonly T[] ya da ReadonlyArray<T> (aynı tip) olarak işaretleyin. push, pop, sort ve splice gibi değiştiren metotlar tipten kaybolur ve indeksle atama bir hatadır. map, filter ve slice gibi değiştirmeyen metotlar çalışmaya devam eder ve sıradan diziler döndürür.

TypeScript'te Readonly derin mi çalışır?

Hayır. Readonly<T> ve readonly yalnızca en üst düzey özellikleri korur; içerideki iç içe nesneler ve diziler yine değiştirilebilir. Tip düzeyinde derin koruma için bir literal üzerinde as const kullanın ya da özyinelemeli bir DeepReadonly<T> tipi yazın.

readonly çalışma zamanında değişiklikleri engeller mi?

Hayır. Tipler silinir, bu yüzden bir readonly özellik çalışma zamanında sıradan bir özelliktir ve aynı nesneye değiştirilebilir bir referansı olan kod (ya da düz JavaScript) onu yine değiştirebilir. Çalışma zamanında koruma gerektiğinde Object.freeze kullanın; TypeScript onun sonucunu Readonly<T> olarak tipler.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA