I get the following errors:
type Union = { type: "1"; foo: string } | { type: "2"; bar: number };
function doSomething = (object: Union) => {
const { foo } = object
// ^ TS2339: Property 'foo' does not exist on type 'Union'.
console.log(object.bar)
// ^ TS2339: Property 'bar' does not exist on type 'Union'.
}
Desired outcome:
typeof foo === string | undefined
typeof bar === number | undefined
How can I access the properties without explicitly type-guarding, for example:
const foo = o.type === 1 ? o.foo : undefined
const bar = o.type === 2 ? o.bar : undefined
this is not really an option for me, beacuse I'm working with large unions, where target properties may or may not be present on many objects, it would be a complete mess.
What other options do I have?
You can set never for unused properties, then TS can understand the type of these properties as optional.
type Type1 = { type: "1"; foo: string, bar?: never }
type Type2 = { type: "2"; foo?: never, bar: number }
type Union = Type1 | Type2
const doSomething = (object: Union) => {
const { type, foo, bar } = object
console.log(type, foo, bar)
}
doSomething({ type: "1", foo: "foo" }) // [LOG]: "1", "foo", undefined
doSomething({ type: "2", bar: 2 }) // [LOG]: "2", undefined, 2
TS Playground link: https://www.typescriptlang.org/play?#code/C4TwDgpgBAKuEEYoF4oG8qkgLigIgTwG4oAzAe3NwGdgAnASwDsBzAGigCMBDOgflxMIANwh0oAXwCwAKCzQ4kAEwp0meLjxLiZSgKhDRdDjzqCArgFtOYyVHtRZ8qAFUmDck1WLEUAD6w8EqysgDGnrRQACbkAMrklhDAABbMLKoAFOScAFYQocC4bh5MAJQoAHzosg5Q4UyRGPIcFOQmvHao2XkFNQ711OQANhAAdEPkLBnNum1cvKWy0jKyMfGJKWkZTRr4hC2Umq14kosyawlJqazb6jj42u1mUCoSZ0A
Check comment in Accessing property in union of object types fails for properties not defined on all union members #12815
The issue here is that because B doesn't declare an a property, it might at run-time have an a property of any possible type (because you can assign an object with any set of properties to a B as long as it has a b property of type string). You can make it work explicitly declaring an a: undefined property in B (thus ensuring that B won't have some random a property):
type A = { a: string; } type B = { b: string; a: undefined } type AorB = A | B; declare const AorB: AorB; if (AorB.a) { // Ok }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With