I try to understand is such behavior a bug?
I defined guard(a: T|undefined) and passed to it value of type "admin"|undefined which is obviously subtype of string|undefined. But guard did not removed |undefined after filtering.
It is tricky for me, because if I change if (user === 'Jack') return 'admin' to if (user === 'Jack') return 'admin' as string; then type guard works correctly, string|undefined becomes string.
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
You could run it in a playground typescrypt playground
The problem is with generic widenind
"admin"tostringYou can make that work the same way, buuuuuut with
typescript@^5Playground
or make an overload for that specific case