Is there a cleaner way to get the value of either property (mutually exclusive) from a union? I can't add a discriminator/kind property because the object type comes from a package I don't maintain, and there's also no class type on either Object. I'd prefer a solution that doesn't require editing the library, casting types (which I currently have to do with as
), or allowing undefined
to be returned.
interface A {
a: true
}
interface B {
b: true
}
function getValue(obj: A | B): boolean | undefined {
let value: boolean | undefined
if (obj.hasOwnProperty("a")) {
value = (obj as A).a
} else if (obj.hasOwnProperty("b")) {
value = (obj as B).b
}
return value
}
You can define custom type guard and use it to narrow the the type:
const isA = (obj: A | B): obj is A => obj.hasOwnProperty("a");
function getValue(obj: A | B): boolean | undefined {
let value: boolean | undefined
if (isA(obj)) {
value = obj.a
} else {
value = obj.b
}
return value
}
// Or shorter
const getValue = (obj: A | B) => isA(obj) ? obj.a : obj.b;
Another option is using in
operator (acts as a narrowing expression for types):
function getValue(obj: A | B): boolean | undefined {
let value: boolean | undefined
if ('a' in obj) {
value = obj.a
} else {
value = obj.b
}
return value
}