如何推断对象键

huangapple go评论132阅读模式
英文:

How to infer object keys

问题

以下是代码部分的中文翻译:

// 创建一个对象,通过遍历数组并只选择需要的元素。示例将更清晰:

const items = [{ type: 'foo' }, { type: 'bar' }, { type: 'baz' }] as const

type MyItems = {
  foo: string | null
  bar: string | null
}

const myItems: MyItems = {
  foo: null,
  bar: null,
}

items.forEach(item => {
  if (item.type in myItems) {
    item.type
      // ^? (属性) type: "foo" | "bar" | "baz"
  }

  if (Object.keys(myItems).includes(item.type)) {
    item.type
      // ^? (属性) type: "foo" | "bar" | "baz"
  }
})

请注意,这是代码的中文翻译部分。如果您有任何其他问题或需要进一步的帮助,请随时告诉我。

英文:

I'm trying to create an object by iterating through an array and only picking the elements that I need. An example will make this clearer:

const items = [{ type: 'foo' }, { type: 'bar' }, { type: 'baz' }] as const

type MyItems = {
  foo: string | null
  bar: string | null
}

const myItems: MyItems = {
  foo: null,
  bar: null,
}

items.forEach(item => {
  if (item.type in myItems) {
    item.type
      // ^? (property) type: "foo" | "bar" | "baz"
  }

  if (Object.keys(myItems).includes(item.type)) {
    item.type
      // ^? (property) type: "foo" | "bar" | "baz"
  }
})

TypeScript playground

My real life example is more complexe and I can't simply reduce on items.

My issue is that TypeScript doesn't infer properly on item.type after the condition and I don't know how to fix this other that with an as that I'd rather not use if possible.

Is there another way of doing this?

答案1

得分: 1

你可以在迭代之前使用type guard function来过滤项目:

items.filter(pickByMyItems).forEach(item => {
  if (item.type in myItems) {
    item.type
      // ^? (属性) type: "foo" | "bar"
  }

  if (Object.keys(myItems).includes(item.type)) {
    item.type
      // ^? (属性) type: "foo" | "bar"
  }
})

你也可以在if条件中使用它:

items.forEach(item => {
  if (pickByMyItems(item)) {
    item.type
      // ^? (属性) type: "foo" | "bar"
  }
})
英文:

You can use a type guard function

const pickByMyItems = 
  <T extends (typeof items)[number]>(item: T): item is Extract<T, { type: keyof typeof myItems }> => 
    Object.keys(myItems).includes(item.type)

to filter the items before iterating them:


items.filter(pickByMyItems).forEach(item => {
  if (item.type in myItems) {
    item.type
      // ^? (property) type: "foo" | "bar"
  }

  if (Object.keys(myItems).includes(item.type)) {
    item.type
      // ^? (property) type: "foo" | "bar"
  }
})

playground

--

you can as well use it in an if condition

items.forEach(item => {
  if (pickByMyItems(item)) {
    item.type
      // ^? (property) type: "foo" | "bar"
  }
})

huangapple
  • 本文由 发表于 2023年3月8日 16:48:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670958.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定