Omit<T, K>, T tipinin K içinde listelenen anahtarlar dışındaki her özelliğini içeren bir nesne tipi oluşturan yerleşik bir utility type'tır. Klasik kullanımı: password alanı olan bir User tipi ve bu alanı içermeyen public bir sürümü.
PublicUser, User ile senkron kalır: User tipine bir alan ekleyin, PublicUser içinde de görünür, password ise dışarıda kalır. Omit yalnızca tipler üzerinde çalışır; özelliği gerçek nesneden kaldıran şey toPublic içindeki destructuring'dir.
Birden Fazla Anahtar Çıkarmak
İkinci argüman bir union'dır; ihtiyaç duyduğunuz kadar anahtarı | ile listeleyin:
"Sunucunun ürettiği alanlar olmadan tip", gerçek kodda en yaygın Omit kullanımıdır: tek bir model tipi vardır ve Omit, oluşturma formları ile API istekleri için girdi şeklini ondan türetir.
Omit Nasıl Tanımlanır
Omit, iki başka utility type'tan oluşur:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
İçten dışa okuyun: keyof T tüm anahtarların union'ıdır, Exclude<keyof T, K> istenmeyenleri bu union'dan çıkarır ve Pick kalan anahtarları tutar. Yani Omit<User, "password">, Pick<User, "id" | "name" | "email"> tipine eşittir. Pick, T tipinin anahtarları üzerinde eşleme yaptığı için kalan özelliklerdeki readonly ve ? değiştiricileri korunur.
Kısıtlamaya dikkat edin: K extends keyof T değil, K extends keyof any. Bir sonraki bölümün konusu bu ayrıntı.
Omit Anahtarın Var Olduğunu Kontrol Etmez
keyof any tipi string | number | symbol olduğu için Omit her anahtarı kabul eder, T tipinde olmayan bir anahtar dahil. Bir yazım hatası derlenir ve hiçbir şey çıkarmaz:
Hiçbir yerde hata yok ve password JSON'da dışarı çıkıyor. Gevşek kısıtlama, Omit TypeScript 3.5'te eklenirken bilerek seçildi. Ekibin gerekçeleri şunlardı: generic kodda çıkarılan anahtarlar çoğu zaman T tipinden gelmez (iki nesneyi birleştiren bir fonksiyon rest argümanını Omit<T1, keyof T2> olarak tipleyebilir), Exclude de ikinci parametresini kısıtlamaz ve kısıtlanmış bir sürüm projelerin zaten sahip olduğu elle yazılmış birçok Omit tipini bozardı. Günlük kod için daha katı bir sürüm yazım hatasını yakalar:
index.ts(10,36): error TS2344: Type '"pasword"' does not satisfy the constraint 'keyof User'.
index.ts(11,7): error TS2741: Property 'password' is missing in type '{ id: number; name: string; }' but required in type 'PublicUser'.
Önemli olan ilk hatadır: anahtar keyof User tipine karşı kontrol edilir. İkincisi ondan kaynaklanır, çünkü hiçbir şey çıkarılmamıştır ve PublicUser hâlâ password ister. Yazımı "password" olarak düzeltin, derlenir. Birçok kod tabanı bunu ortak bir tipler dosyasında bir kez tanımlar ve Omit yerine kullanır.
Bir Özelliğin Tipini Ezmek
Bir interface başka birini extend edip bir özelliği uyumsuz bir tipe çeviremez: interface ApiUser extends User { id: string } şu hatayla başarısız olur: error TS2430: Interface 'ApiUser' incorrectly extends interface 'User'. Önce özelliği omit edin, sonra yeniden bildirin:
Bir type alias ile aynı şey bir intersection'dır: type ApiUser = Omit<User, "id"> & { id: string }. Omit olmadan User & { id: string } intersection'ı id alanına number & string tipini, yani never tipini verirdi.
Union Tiplerde Omit
Omit dağıtıcı (distributive) değildir. Bir union üzerinde, tüm union'ın keyof tipinden başlar; bu tip yalnızca her üyenin paylaştığı anahtarları içerdiği için üyelerin kendine ait özellikleri kaybolur:
index.ts(8,39): error TS2353: Object literal may only specify known properties, and 'radius' does not exist in type 'NewShape'.
NewShape, { kind: "circle" | "square" } hâline geldi. Her üyeden ayrı ayrı çıkarmak için Omit tipini dağıtıcı bir conditional type içinde uygulayın:
T extends unknown ? ... : never her zaman doğrudur; yalnızca conditional type'ın union üzerine dağılmasını sağlamak için oradadır. Bunun neden çalıştığını conditional types sayfası açıklar. Omit uyguladığınız tip bir discriminated union olduğunda DistributiveOmit kullanın.
İç İçe Bir Özelliği Çıkarmak
Omit yalnızca en üst düzey anahtarlara bakar, bu yüzden Omit<Settings, "editor.wordWrap"> hiçbir şey çıkarmaz (ve yukarıda görüldüğü gibi şikâyet de etmez). Bir düzey aşağıdaki bir özelliği çıkarmak için üst özelliği omit edin ve onu kendi Omit tipiyle geri ekleyin:
Settings["editor"] bir indexed access type'tır: Omit üzerinde çalışabilsin diye iç içe nesne tipini adlandırır.
Özellikleri Çalışma Zamanında Silmek
Omit yalnızca tipi değiştirir. Özellikleri olmayan bir nesne üretmek için onları destructuring ile ayırın ya da dönüş tipi Omit olan küçük bir generic yardımcı yazın:
Yardımcı K tipini keyof T ile kısıtlar, bu yüzden yanlış yazılmış bir anahtar çağrı yerinde hata verir. Kopya sığdır: iç içe nesneler orijinal ile paylaşılır.
Omit, Pick ve Exclude
| Üzerinde çalıştığı | Tuttuğu | Örnek | Sonuç | |
|---|---|---|---|---|
Omit<T, K> | nesne tipleri | K dışındaki her özellik | Omit<User, "password"> | { id; name; email } |
Pick<T, K> | nesne tipleri | yalnızca K içindeki özellikler | Pick<User, "id" | "name"> | { id; name } |
Exclude<U, M> | union tipler | M tipine atanamayan union üyeleri | Exclude<"a" | "b" | "c", "a"> | "b" | "c" |
Omit ile Pick arasında, kaynak tip büyüdüğünde ne olması gerektiğine göre seçim yapın. Omit yeni özellikleri otomatik olarak dahil eder; bu da "sır dışında her şey" durumuna uyar. Pick onları asla dahil etmez; bu da "tam olarak bu alanlar" durumuna uyar ve sunucunuzdan dışarı çıkan her şey için daha güvenlidir. Pick anahtarlarını keyof T tipine karşı kontrol eder; Omit etmez.
Sıkça Sorulan Sorular
TypeScript'te Omit ne işe yarar?
Omit<T, K>, T tipinin anahtarları K içinde olanlar dışındaki tüm özelliklerini içeren yeni bir nesne tipi oluşturur. Omit<User, "password">, password olmadan User tipidir. Yalnızca tipi değiştirir; çalışma zamanında bir nesneden hiçbir şey silmez.
TypeScript'te birden fazla özelliği nasıl omit ederim?
İkinci argüman olarak anahtarlardan oluşan bir union geçirin: Omit<User, "password" | "createdAt" | "updatedAt">. Union'daki her anahtar çıkarılır.
Omit ile Exclude arasındaki fark nedir?
Omit bir nesne tipinden özellik çıkarır: Omit<{ a: 1; b: 2 }, "a"> sonucu { b: 2 } olur. Exclude bir union tipinden üye çıkarır: Exclude<"a" | "b", "a"> sonucu "b" olur. Omit, Exclude ile uygulanmıştır: Pick<T, Exclude<keyof T, K>>.
Omit var olmayan bir anahtar için neden hata vermiyor?
Anahtar parametresi keyof T ile değil keyof any (herhangi bir string, number ya da symbol) ile kısıtlanmıştır; bu yüzden Omit<User, "pasword"> gibi bir yazım hatası derlenir ve hiçbir şey çıkarmaz. Bilinmeyen anahtarlarda hata almak için type StrictOmit<T, K extends keyof T> = Omit<T, K> tanımlayın.
TypeScript'te bir nesneden özelliği çalışma zamanında nasıl silerim?
Rest elemanlı destructuring kullanın: const { password, ...rest } = user;. TypeScript rest değerini password olmadan nesne olarak, yani Omit<User, "password"> ile aynı şekilde tipler ve özellik yeni nesneden gerçekten kalkmış olur.