【问题标题】:Deep intersection type of two object types in TS [duplicate]TS中两种对象类型的深度交集类型[重复]
【发布时间】:2021-02-24 22:31:44
【问题描述】:

对于两种对象类型的深度/递归交集,是否有类似“&”的东西?这意味着只允许访问所有合并类型中存在的属性。

这是我想做的:

// Defined in its own file
const en = {
  "welcome": {
    "hello": "Hello",
    "world": "World"
  }
}

// Defined in its own file
const hu = {
  "welcome": {
    "hello": "Helló világ"
  }
}

// How to write this type?
// Should be deep intersection,
// meaning only mutually available properties allowed
let locale: typeof en & typeof hu

//  Using a Webpack resolve.alias
//  resolve.alias.locales = path.resolve(
//    __dirname,
//    `locales/${process.env.NEXT_PUBLIC_LOCALE}`
//  )
//@ts-ignore
locale = {}

locale.welcome.world // This should NOT be available
locale.welcome.hello // This SHOULD be availeble

【问题讨论】:

  • 您说的是联合 (|),而不是交集,它的行为已经如此。

标签: typescript typescript-typings intersection recursive-type


【解决方案1】:

您需要使用union 来获得两者的共同点。我知道它在语言上(维恩图)是相反的,但它是这样工作的。 (我强烈建议您阅读@jcalz 提供的有关此答案的 cmets 和链接,以更好地解释为什么从类型分配的角度来看 &| 是有意义的。)

TS Playground

const en = {
  welcome: {
    hello: "Hello",
    world: "World",
  },
};

const hu = {
  welcome: {
    hello: "Helló világ",
  },
};

let locale = {} as typeof en | typeof hu;

// Error: Property 'world' does not exist on type '{ hello: string; world: string; } | { hello: string; }'.
locale.welcome.world; // This should NOT be available

// Works
locale.welcome.hello; // This SHOULD be availeble

【讨论】:

  • 这似乎是一个常见的混淆。类型对应于JavaScript 值集,而不是对象属性名称集(参见this Q/A)。 A | B 类型的值可以是A 类型的值或B 类型的值;如果AB 是对象类型,那么您只能安全地访问这两种类型中存在的属性。 A & B 类型的值必须是 A 类型和 B 类型的值;如果AB 是对象类型,那么您可以安全地访问任一类型的属性。换句话说,keyof is contravariant.
猜你喜欢
  • 2013-06-06
  • 2021-03-22
  • 2012-01-10
  • 2021-12-31
  • 2016-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
相关资源
最近更新 更多