I'm having a problem properly typing an object key to an enum. This is essentially what I have:
enum ItemTypes {
WOOD,
STONE
}
interface Item {
owned: number,
max: number
}
const stockpile: {[key in ItemTypes]: Item} = {}
I'm getting an error where stockpile
is expecting the itemType
enums to already exist within stockpile
Doing this works:
const stockpile: { [key: string]: Item } = {}
However, I would prefer it to be better typed as well as being able to export the enum to be used elsewhere. How would I go about this?
CodePudding user response:
THere is a big difference between stockpile
and stockpile2
const stockpile: {
[key in ItemTypes]: Item
} = {}
const stockpile2: {
[key: string]: Item
} = {}
stockpile
is and object with up front defined required keys 0
and 1
. So, TS forbis you to use empty object when it expects two keys
stockpile2
is just indexed object. It means that there are no required keys/properties, however each key should be a string.
Summary
If you want to make required keys, you should use [key in ItemTypes]
otherwise use [key: string]: Item
Hence, if you want to allow only keys from ItemTypes
, use :
enum ItemTypes {
WOOD,
STONE
}
interface Item {
owned: number,
max: number
}
type Stockpile = Partial<Record<ItemTypes, Item>>
const stockpile: Stockpile = {} // ok
const stockpile2: Stockpile = {
0: { owned: 1, max: 2 }
} // ok
const stockpile3: Stockpile = {
0: { owned: 1, max: 2 },
1: { owned: 1, max: 2 }
} // ok
Please keep in mind, that numerical enums are unsafe. Please see my article
Here you can find documentation about utility types: Partial, Record etc ...