This is part of my TypeScript code.
enum FirstEnum {
firstEnumKey1 = 'firstEnumKey1',
firstEnumKey2 = 'firstEnumKey2',
firstEnumKey3 = 'firstEnumKey3',
firstEnumKey4 = 'firstEnumKey4',
}
enum SecondEnum {
secondEnumKey1 = 'secondEnumKey1',
secondEnumKey2 = 'secondEnumKey2',
secondEnumKey3 = 'secondEnumKey3',
}
// map first enum to second enum
const map: {[i in FirstEnum]: SecondEnum[] } = {
'firstEnumKey1': [SecondEnum.secondEnumKey1],
'firstEnumKey2': [],
'firstEnumKey3': [SecondEnum.secondEnumKey2, SecondEnum.secondEnumKey3],
'firstEnumKey4': [SecondEnum.secondEnumKey2, SecondEnum.secondEnumKey3],
};
I have two enums and a const which map them. I’m using the map to define some data that for each SecondEnum has an object. The object keys should be map keys which had that specific SecondEnum value in their array.
So now my result should be like this.
const getSecondEnumValuesBasedOnMap = {
[SecondEnum.secondEnumKey1]: {
[FirstEnum.firstEnumKey1]: 'some value',
},
[SecondEnum.secondEnumKey2]: {
[FirstEnum.firstEnumKey3]: 'some value',
[FirstEnum.firstEnumKey4]: 'some value',
},
[SecondEnum.secondEnumKey3]: {
[FirstEnum.firstEnumKey3]: 'some value',
[FirstEnum.firstEnumKey4]: 'some value',
},
}
If I change my map my data should change based on it. for example if I add SecondEnum.secondEnumKey2
to FirstEnum.firstEnumKey2
my data should change like this:
// map first enum to second enum
const map: {[i in FirstEnum]: SecondEnum[] } = {
'firstEnumKey1': [SecondEnum.secondEnumKey1],
'firstEnumKey2': [SecondEnum.secondEnumKey2],
'firstEnumKey3': [SecondEnum.secondEnumKey2, SecondEnum.secondEnumKey3],
'firstEnumKey4': [SecondEnum.secondEnumKey2, SecondEnum.secondEnumKey3],
};
const getSecondEnumValuesBasedOnMap = {
[SecondEnum.secondEnumKey1]: {
[FirstEnum.firstEnumKey1]: 'some value',
},
[SecondEnum.secondEnumKey2]: {
[FirstEnum.firstEnumKey2]: 'some value',
[FirstEnum.firstEnumKey3]: 'some value',
[FirstEnum.firstEnumKey4]: 'some value',
},
[SecondEnum.secondEnumKey3]: {
[FirstEnum.firstEnumKey3]: 'some value',
[FirstEnum.firstEnumKey4]: 'some value',
},
}
I want to declare a type for my result so when I changed my map I get errors to update my result but I’m kind of new to typescript and I don’t know how.
3
Answers
declare type like this:
}
then use like this:
const getSecondEnumValuesBasedOnMap: GetSecondEnumValuesBasedOnMap = { [SecondEnum.secondEnumKey1]: { [FirstEnum.firstEnumKey1]: 'some value', }
I think it would be better to declare the map as a type rather than a constant (assuming you do not also need to use it in your calculations).
If you do that and also invert the keys and values to make the mapping easier, you can declare all the types like this:
Playground Link
First of all, we need to change the type of the
map
, since it is currently not having literal values for theSecondEnum
and we won’t be able to determine which exact values are used.To prevent the compiler from widening the types we will use const assertion and to maintain type safety we will use satisfies operator:
Next, let’s define a type that accepts a generic parameter constrained by
SecondEnum
and find the members ofFirstEnum
that have this specific item in themap
. We are going to use mapped types to map through themap
and key remapping to exclude those that are not suitable, and at the end return the keys of themap
that have this second enum in them:Let’s define a type for the
getSecondEnumValuesBasedOnMap
. We will need to usemapped types
andkey remapping
again to exclude those second enum members that are not used at all:Note that
[]
are really important in the[FindValue<K>] extends [never]
, sincenever
is an empty set and is a supertype for every union and to make sure that this check works as expected we prevent the compiler from distributing the types using the[]
.And in the values, we are mapping through the result of
FindValue<K>
which returns as the keys where the second enum is used and assigns a value of typestring
:playground