Search code examples
typescripttypescript2.0type-systemsunion-types

Can't narrow simple TypeScript union type with undefined property


I have two unioned types, one has a property and the other one hasn't. I assumed that checking for the existence of that property would allow me to narrow it down, but it isn't working.

I've created this Playground repro. This other very similar thing seems to work just fine. Am I using unions the wrong way?

Here's the code for the sake of completeness:

export interface AuthenticatedProfile {
    readonly userId: string;
    readonly name: string;
}
export interface AnonymousProfile {
    readonly userId: undefined;
    readonly otherProp: string;
}
export type Profile = AnonymousProfile | AuthenticatedProfile;

function handleProfile(prof: Profile) {
    if (prof.userId) {
        console.log(prof.name);
    }
}

Thanks!


Solution

  • You can use type guards to restrict the type of the prof parameter.

    export interface AuthenticatedProfile {
        readonly userId: string;
        readonly name: string;
    }
    export interface AnonymousProfile {
        readonly userId: undefined;
        readonly otherProp: string;
    }
    export type Profile = AnonymousProfile | AuthenticatedProfile;
    
    function isAuthenticatedProfile(prof: Profile): prof is AuthenticatedProfile {
        return (<AuthenticatedProfile>prof).name !== undefined;
    }
    
    function isAnonymousProfile(prof: Profile): prof is AnonymousProfile {
        return (<AnonymousProfile>prof).otherProp !== undefined;
    }
    
    function handleProfile(prof: Profile) {
        if (isAuthenticatedProfile(prof)) {
            console.log(prof.name);
        } else if (isAnonymousProfile(prof)) {
            console.log(prof.otherProp);
        }
    }
    

    You can read more about type guards in typescript in the Advanced Types section in the handbook.