Search code examples
if-statementtypescriptobject-properties

Accessing different properties in a typescript union type


I'm creating a function that handles objects from the database. I have two different data structures where the same property has a different name. I can't change that, so I have to handle it in JavaScript.
The objects have other differences, but that's not important to this function.
I want to use the same function for two different types of objects. Here's sample code demonstrating my problem:

interface TypeA {
    itemName: string;
}

interface TypeB {
    itemTitle: string;
}

function getItemName(item: TypeA | TypeB): string {
    let name = '';

    if (item.hasOwnProperty('itemName')) {
        name = item.itemName;
    } else {
        name = item.itemTitle;
    }

    return name;
}

Of course, this code runs. But the IDE marks both the lines name = item.itemName; and name = item.itemTitle; as errors ("Property does not exist on type"), because both types do not have both properties.

So, what's the proper typescript way to do this?


Solution

  • You need to create a User Defined Type Guard, then you can use an if statement and get the correct typing.

    function isTypeA(value: TypeA | TypeB): value is TypeA {
        return value.hasOwnProperty('itemName');
    }
    

    Then you can get the typing much cleaner:

    function getItemName(item: TypeA | TypeB): string {
        return isTypeA(item) ? item.itemName : item.itemTitle;
    }
    

    Check it out here. Item is correctly cast to either TypeA or TypeB.