Reputation: 2177
This is a situation I have ran into a couple of times, it seems like it should be fairly straightforward, but I can't find a solution that doesn't set the type to any
A function takes one of two different objects as the argument, checks which object has been received, and returns the corresponding field.
This is a simplified version of the problem, but the issue is that the two objects are only distinguishable by their properties(which have no overlap), and I can't access any of the properties, because they're not present on the other type.
type Obj1 = {
message: string
}
type Obj2 = {
text: string
}
const getText = (obj: Obj1 | Obj2): string => {
if (obj.message) {
return obj.message
}
return obj.text
}
Upvotes: 194
Views: 66785
Reputation: 37584
You have to narrow down the type. You can do so by using the in
operator.
const getText = (obj: Obj1 | Obj2): string => {
if ("message" in obj) {
return obj.message
}
return obj.text
}
Upvotes: 343
Reputation: 4067
The real answer to this problem according to what the question owner asked is this
But there might be a time you are using your defined type
with primitive type
in this way the above solution is not going to work as the problem I faced
here is the situation
type Obj1 = {
message: string
}
const getText = (obj: Obj1 |string): string => {
if (obj.message) {
return obj.message
}
return obj.text
}
so this scenario the solution stated above would not be perfect for you, so you might need to use typeof
✌️
const getText = (obj: Obj1 | string): string => {
if (typeof obj !== 'string') {
return obj.message
}
return obj.text
}
Upvotes: 6
Reputation: 513
I recommend typescript-is.
import { is } from 'typescript-is';
...
const getText = (obj: Obj1 | Obj2): string => {
if (is<Obj1>(obj)) {
return obj1.message;
}
return obj2.text;
};
Upvotes: 1
Reputation: 2835
You can cast the object to either Obj1
or Obj2
:
type Obj1 = {
message: string
}
type Obj2 = {
text: string
}
const getText = (obj: Obj1 | Obj2): string => {
if ((obj as Obj1).message) {
return (obj as Obj1).message
}
return (obj as Obj2).text
}
Upvotes: 52