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"
tostring
You can make that work the same way, buuuuuut with
typescript@^5
Playground
or make an overload for that specific case