Typescript neden bu senaryoda birleşim tipi ile hata gösteriyor?
Bu senaryoda:
type Type = {
a: string;
b: string;
} | {
a: number;
b: number;
};
const func = ({a, b}: Type): string => {
if (typeof a === 'string') {
return b;
}
return 'w/e';
}
func({a: 1, b: 'w/e'});
return b; üzerinde bir hata alıyorum, belirtilen
‘string | number’ türü, ‘string’ türüne atanamaz.
Type 'number', type 'string' olarak atanamaz.
Hatanın anladığım kadarıyla, Typescript Type tipini olarak yorumluyor
type Type = {
a: string | number;
b: string | number;
};
, ama durum böyle olsa bile, neden func fonksiyonunu bir string ve bir sayı ile çağıramıyorum?
Aramadaki hata şunu belirtiyor
Type '{ a: number; b: string; }' türündeki argüman, 'Type' türündeki parametreye atanamaz.
'{ a: number; b: string; }' türü, '{ a: number; b: number; }' türüne atanamaz.
'b' türündeki özellikler uyumsuzdur.
'string' tipi, 'number' tipine atanamaz.
(ts sürümü: 4.7.2)
Oyun alanı linki
- UnholySheep'in yorumundan sonra düzenle:
Yanlış türlerle yapılan fonksiyon çağrısı, sadece önceki hatayı neden aldığımı test etmek içindi. Anlamadığım şey, neden return b; satırında hata aldığım.
Cevap #1
Tamam, cevap Discriminated Unions. Bir ayrımcı, yani birleştirme içindeki her öğede ortak bir özelliği kullanmam gerekiyor. O ayrımcı özellik:
- Bir ilkel tür olmalı ve
- Belirli bir değere sahip olmalı ve o değerin türü olmamalıdır. Örneğin
isPrimary: true,isPrimary: booleandeğil.
O zaman diğer özelliklerin türlerini varsaymak için o özelliğin değerini kontrol edebilirim.
Ayrıca, Typescript sürümleri < 4.6'da, eğer yukarıda belirtilen türde bir objem varsa, onu yapıbozum (destructure) yaparsam, yeni değişkenler bağımsız olarak kabul edilir ve başlangıçtaki örneğe benzer bir hata almaya devam ederim. Yapıbozum 4.6 veya daha yüksek sürümlerde çalışır.
Oyun alanı örneği (sürüm 4.6)
Oyun alanı örneği (sürüm 4.5)
Yararlı bağlantılar:
- @Austaras'ın Microsoft'un parçalara ayırma desteğini duyurduğu gönderiye bağlantısı
- Ayrımcı Birleşimleri Anlamak
- Typescript'in Singleton tipleri
Teşekkürler @Austaras ve @coglialoro
Cevap #2
TS, a ve b öğelerini parçalamadan sonra arasındaki ilişkiyi takip edemez, bu nedenle ikisi de string | number olarak çıkarılır. TS 4.6, yalnızca ayrımlı birleşimlere uygulanan sınırlı bir kontrol akışı analizi getirdi.