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?
you can make a type assertion if you don't do this too often :
or
if you need to make this check more than once or twice, you'd better writing a type guard as @Daryl suggests.
I won't complicate things. If you're really sure that your object has either the one or the other property, a
name = item['itemName'] || item['itemTitle']
orname = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle']
would be sufficient.Note that TypeScript usually stops complaining if you access properties using the bracket notation instead of the dot notation. I would suggest adding a comment, though.
Intellij accepts this syntax:
the official way according to the typescript docs is this: https://www.typescriptlang.org/docs/handbook/functions.html
Use typeguards:
You need to create a User Defined Type Guard, then you can use an if statement and get the correct typing.
Then you can get the typing much cleaner:
Check it out here. Item is correctly cast to either TypeA or TypeB.