typeguards - Typescript tür koruyucusu çıkarımsız string literali
Böyle bir davranışın bir hata olup olmadığını anlamaya çalışıyorum?
guard(a: T|undefined) tanımladım ve ona "admin"|undefined türünde bir değer verdim ki bu açıkça string|undefined türünün alt türü. Ama guard filtreledikten sonra |undefined kısmını kaldırmadı.
Benim için zor, çünkü eğer if (user === 'Jack') return 'admin' kodunu if (user === 'Jack') return 'admin' as string; olarak değiştirirsem, tip koruması doğru çalışıyor ve string|undefined string oluyor.
function getPermissions(user: string){
if (user === 'Jack') return 'admin';
return undefined;
}
const admins = ['Mike', 'Joe'].map(e => getPermissions(e)); //type ("admin"|undefined)[]
function isDefined<T>(a: T | undefined): a is T {
return a !== undefined;
}
const foundAdmins = admins.filter(isDefined); //type is ("admin"|undefined)[] but string[] expected
Bunu bir playground TypeScript playground'unda çalıştırabilirsiniz
Cevap #1
Sorun, genel genişletme "admin" den string e yapılıyor
Bunu aynı şekilde yapabilirsiniz, ama typescript@^5 ile
Oyun alanı
function getPermissions(user: string){
if (user === 'Jack') return 'admin';
return undefined;
}
const admins = ['Mike', 'Joe'].map(e => getPermissions(e)); //type ("admin"|undefined)[]
function isDefined<T>(a: T | undefined): a is T {
return a !== undefined;
}
const foundAdmins = admins.filter(isDefined);
// ^?
// const foundAdmins: ("admin" | undefined)[]
function isDefinedWithConst<const T>(a: T | undefined): a is T {
return a !== undefined;
}
const foundAdmins2 = admins.filter(isDefinedWithConst);
// ^?
// const foundAdmins2: "admin"[]
// dirty but works
const foundAdmins3 = admins.filter((e): e is 'admin' => isDefined<'admin'>(e));
// ^?
// const foundAdmins3: "admin"[]
veya o özel durum için bir aşırı yükleme yap
function nonNullable<T>(v: T | null | undefined): v is T { return v != null }
interface Array<T> {
filter(p: typeof nonNullable): NonNullable<T>[]
}
const foundAdmins4 = admins.filter(nonNullable);
// ^?
// const foundAdmins4: "admin"[]
