我得到以下错误:
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'.
}
期望结果:
typeof foo === string | undefined
typeof bar === number | undefined
如何在没有显式类型保护的情况下访问属性,例如:
const foo = o.type === 1 ? o.foo : undefined
const bar = o.type === 2 ? o.bar : undefined
这对我来说不是一个真正的选择,因为我正在处理大型联合,其中目标属性可能存在也可能不存在于许多对象中,这将是一个完全混乱的
我还有其他选择吗?
在对象类型的联合中访问属性失败,因为没有在所有联合成员上定义属性#12815
这里的问题是,因为B没有声明a属性,它可能在运行时具有任何可能类型的a属性(因为您可以将具有任何属性集的对象分配给B,只要它具有类型为string的B属性)。你可以让它显式地在B中声明a: undefined属性(从而确保B不会有一些随机的a属性):
type A = { a: string; } type B = { b: string; a: undefined } type AorB = A | B; declare const AorB: AorB; if (AorB.a) { // Ok }
您可以为未使用的属性设置never
,然后TS可以将这些属性的类型理解为可选的。
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游乐场链接:https://www.typescriptlang.org/play?代码/C4TwDgpgBAKuEEYoF4oG8qkgLigIgTwG4oAzAe3NwGdgAnASwDsBzAGigCMBDOgflxMIANwh0oAXwCwAKCzQ4kAEwp0meLjxLiZSgKhDRdDjzqCArgFtOYyVHtRZ8qAFUmDck1WLEUAD6w8EqysgDGnrRQACbkAMrklhDAABbMLKoAFOScAFYQocC4bh5MAJQoAHzosg5Q4UyRGPIcFOQmvHao2XkFNQ711OQANhAAdEPkLBnNum1cvKWy0jKyMfGJKWkZTRr4hC2Umq14kosyawlJqazb6jj42u1mUCoSZ0A
这种行为是有意义的,因为TS不知道它正在处理的是来自Union的哪个对象,并且在某些情况下该属性不存在。
我不确定这是否是你想要的,但你可以尝试像
这样的东西type Union = { type: "1"; foo: string } | { type: "2"; bar: number };
function doSomething = (object: Union) => {
if ('foo' in object) {
const { foo } = object
}
if ('bar' in object) {
console.log(object.bar)
}
}
这是一个操场
我发现最方便的方法是根据变量的类型强制转换。
type Type1 = { type: "1"; foo: string }
type Type2 = { type: "2"; bar: number }
type Union = Type1 | Type2
function doSomething = (object: Union) => {
const { foo } = object as Type1
const { bar } = object as Type2
const { type } = object
}