【问题标题】:How to create interface of object with predefined keys?如何使用预定义的键创建对象接口?
【发布时间】:2020-01-22 17:16:04
【问题描述】:

我有数据对象:

const data = [
      {
        type: 'soccer',
        price: '$10'
      },
      {
        type: 'running',
        price: '$5'
      },
      {
        type: 'hockey',
        price: '$15'
      }
    ]

我想将它转换为 key 为 item.type 的对象:

const parsedData = {
  soccer: {
    type: 'soccer',
    price: '$10'
  },
  running: {
    type: 'running',
    price: '$5'
  },
  hockey: {
    type: 'hockey',
    price: '$15'
  }
}

我已经用类型定义了枚举:enum GameTypes { 'soccer', 'running', 'hockey' }。当我尝试使用枚举作为对象的键时,我得到了错误: 元素隐式具有“any”类型,因为“GameTypes”类型的表达式不能用于索引“GameProducts”类型。 类型“GameProducts”.ts(7053) 上不存在属性“[GameTypes.lottery]”

完整代码:

enum GameTypes { 'soccer', 'running', 'hockey' }

type Game = {
  type: GameTypes
  price: string
}

type GameProducts = { [key in GameTypes]?: Game } | {}

const data: Array<Game> = [
  {
    type: 'soccer',
    price: '$10'
  },
  {
    type: 'running',
    price: '$5'
  },
  {
    type: 'hockey',
    price: '$15'
  }
]

// trying to format games in object
const formatGames: GameProducts = data.reduce((acc | {}, item) => {
    if (!acc[item.type]) {  // <-- error here
      acc[item.type] = []
    }
    acc[item.type].push(item)

    return acc
  }, {})

我做错了什么?还有其他方法吗?

【问题讨论】:

    标签: typescript enums


    【解决方案1】:

    有几个问题需要解决:

    • GameProduct 未定义,应该由 Game 代替
    • GameProducts 映射到一个数组而不是一个简单的对象
    • 为了让 reducer 理解代码并适当地 lint,使用如下所示的不可变代码会更容易
    • 使用需要使用映射GameTypes['some_value'] 以便转译器确认您的代码。

    enum GameTypes { 'soccer', 'running', 'hockey' }
    
    type Game = {
      type: GameTypes
      price: string
    }
    
    type GameProducts = { [key in GameTypes]?: Game[] };
    
    const data: Array<Game> = [
      {
        type: GameTypes['soccer'],
        price: '$10'
      },
      {
        type: GameTypes['running'],
        price: '$5'
      },
      {
        type: GameTypes['hockey'],
        price: '$15'
      }
    ]
    
    // formatting games object
    const formatGames: GameProducts = data.reduce((acc: GameProducts, item) => {
        if (!acc[item.type]) {
            acc[item.type] = [];
        }
    
        acc[item.type] = [
            ...(acc[item.type] || []),
            item
        ];
    
        return acc
    }, {});
    
    console.log(formatGames);

    您也可以使用:

    enum GameTypes { Soccer = 'soccer', Running = 'running', Hockey = 'hockey' }
    
    const data: Array<Game> = [
      {
        type: GameTypes.Soccer,
        price: '$10'
      }
    ]
    

    或者更简单的解决方案:

    type GameTypes = 'soccer' | 'running' | 'hockey';
    
    const data: Array<Game> = [
      {
        type: 'soccer',
        price: '$10'
      }
    ]
    

    这样也可以。

    【讨论】:

    猜你喜欢
    • 2017-08-21
    • 2010-09-17
    • 2023-04-05
    • 2012-10-20
    • 2021-12-08
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    相关资源
    最近更新 更多