ProgramlamaFullstack geliştirici

TypeScript'te Exclude nasıl çalışır, union türleri ile manipülasyonlar için ne zaman kullanılmalıdır ve bu yardımcı tür ile çalışırken hangi nüanslar vardır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Exclude<T, U> — TypeScript'te bir türü diğerinden çıkarmak için kullanılabilen bir utility type olup, union türünden bazı değerleri hariç tutmak için gereklidir.

Konunun Tarihi

TypeScript'te bir türü diğerinden çıkarmanın kullanışlı bir yolu yoktu. Genel API'ler oluşturulurken ya da refaktörizasyon sırasında genellikle "artık" türü almak gerekiyordu — yasaklı değerler dışında her şey. Birkaç benzer arabirimi desteklemek yerine union üzerinde manuel işlem yapmak sıkıntılıydı.

Problem

Örneğin, 'A | B | C' türü varsa, fakat B hariç tür almak gerekiyorsa. Bu sıkça, fonksiyonların karmaşık giriş parametrelerini oluştururken, izin verilen değerleri filtrelerken ve dinamik türler oluştururken gerekir.

Çözüm

Exclude bu problemi çözer. Kolaylaştırılmış imzası şöyledir:

type Exclude<T, U> = T extends U ? never : T;

Bu, T'den U'daki tüm üyeleri hariç tutarak bir tür döndürür.

Örnek:

type Status = 'draft' | 'published' | 'removed'; type UserVisibleStatus = Exclude<Status, 'removed'>; const visible: UserVisibleStatus = 'draft'; // TAMAM

Anahtar özellikler:

  • Union'dan parçaların "çıkartılması" sayesinde dinamik türler oluşturmaya olanak tanır.
  • Refactoring'i basitleştirir — temel tür değiştiğinde tüm türevler otomatik olarak güncellenir.
  • Örneğin, switch durumlarını ya da bir nesnenin anahtarlarını filtrelemek için kullanılabilir.

Soru-Cevap.

Exclude normal türler için de kullanılabilir mi, yoksa sadece union için mi?

Eğer T union tür değilse ama U'da bulunuyorsa — Exclude yine çalışır, fakat sonucu never veya T olabilir, bu her zaman sezgisel olmayabilir.

Exclude<'a', 'a'> // sonuç: never Exclude<'a', 'b'> // sonuç: 'a'

Exclude bir türün nesne yapısındaki tüm referanslarını siler mi?

Hayır, Exclude, bir türdeki iç içe alanları rekürsif olarak geçmez, sadece union'ın üst düzeyinde hariç tutar.

Exclude arayüzlerle ve nesne türleriyle nasıl çalışır?

Tüm türü karşılaştırır, ayrı ayrı özellikleri değil. Bu nedenle birden fazla arayüzün union'ından Exclude, yalnızca U ile tam olarak eşleşenleri siler.

interface A { x: number }; interface B { y: string }; // Exclude<A|B, B> verir: A (B tam olarak eşleşiyor)

Türsel hatalar ve anti-paternler

  • Exclude'ü iç içe veya kısmi eşleşmeler için kullanma girişimleri
  • Union türleri yerine bir arayüzün özelliklerini "silmek" için kullanılması
  • Türlerin tam eşleşmesi durumunda never türünü almak olasılığını görmezden gelme

Hayattan bir örnek

Olumsuz durum

Kullanıcı rolleri doğrulaması için Exclude<UserRoles, 'admin'> kullanıldı, ama Exclude'ün iç içe yapılara uygulanmadığı unutuldu — 'admin:sub' hakkı hariç tutulmadı.

Artılar:

  • Rol türlerinin oluşturulmasındaki basitlik.

Eksiler:

  • İç içe veya benzer türlerle ilgili anlaşılmaz davranış; kritik bir rol kaçırıldı.

Olumlu durum

Public API'yi eylemlerle kısıtlamak için Exclude kullanımı: Exclude<Action, 'delete'>, bu da tehlikeli bir işlemi hariç tutar.

Artılar:

  • Türlemeyi güvenli hale getirir, yasaklı bir eylem çağrılamaz.

Eksiler:

  • Temel türlerin güncel listesini sürdürmek gerekir.