Reputation:
THE PROBLEM:
I have a switch Statement. The comparison is based on two enums
. But the conditions are all returning false.
POSSIBLE SOLUTION FOUND ON STACK_OVERFLOW:
I read somewhere, that in order to avoid this, you have to put a +
in the case like so:
switch(+resources) instead of switch(resources)
This has the side effect, of transforming the case
in a number, which makes TS, quite unhappy since my enums
are strings
.
SAMPLE CODE: The enums, I want to use in my Function:
enum ResourceTypes {
RESOURCE1 = 'RESOURCE1',
RESOURCE2 = 'RESOURCE2',
RESOURCE3 = 'RESOURCE2',
}
export default ResourceTypes;
enum OperationTypes {
OPERATION1 = 'OPERATION1',
OPERATION2 = 'OPERATION2',
OPERATION3 = 'OPERATION3',
OPERATION4 = 'OPERATION4'
}
export default OperationTypes;
The Function, that reverts always to the default case, is simply checking the resourceType
, and returns an array of operations:
import ResourceTypes from '../enums/ResourceTypes';
import OperationTypes from '../enums/OperationTypes';
const operationPerResource = (resource: any): OperationTypes[] => {
const { RESOURCE1, RESOURCE2, RESOURCE3 } = ResourceTypes;
const { OPERATION1, OPERATION2, OPERATION3, OPERATION4 } = OperationTypes;
switch (resource) {
case RESOURCE1:
return [OPERATION2, OPERATION3, OPERATION4];
case RESOURCE2:
return [OPERATION1, OPERATION2, OPERATION3];
case RESOURCE3:
return [OPERATION1, OPERATION2];
default:
return [];
}
};
export default operationPerResource;
And this is where I call the function:
const resources = transformEnumToArray(ResourceTypes);
const operations = operationPerResource(resources.value).map((value: any) => ({
label: value,
value
}));
This is the transofrmEnumToArray Function:
const transformEnumToArray = (object: object): any =>
Object.keys(object).map(value => ({
label: value,
value
}));
export default transformEnumToArray;
A few details on the implementation. operations
is used in a React-Select Component. So, for every selection, I make on one field(Resources), I get the available Operations in another.
The resources.value, is printed in the console. I get everything back , in a label, value
object, as per every react-select.
I mean, what am I doing wrong here? Why is the comparison for the enums, aren't working. Can you guys help me out here? I tested this with constants
instead of enums and it works just fine. So what is the difference with enums
in Typescript? Thank you
Upvotes: 0
Views: 4959
Reputation: 1572
If you use the switch
expression in a function with typed parameter, this works as expected.
Example:
enum ResourceTypes {
RESOURCE1 = 'RESOURCE1',
RESOURCE2 = 'RESOURCE2',
RESOURCE3 = 'RESOURCE2',
}
enum OperationTypes {
OPERATION1 = 'OPERATION1',
OPERATION2 = 'OPERATION2',
OPERATION3 = 'OPERATION3',
OPERATION4 = 'OPERATION4',
}
const operationPerResource = (resource: ResourceTypes): OperationTypes[] => {
const { RESOURCE1, RESOURCE2, RESOURCE3 } = ResourceTypes;
const { OPERATION1, OPERATION2, OPERATION3, OPERATION4 } = OperationTypes;
switch (resource) {
case RESOURCE1:
return [OPERATION2, OPERATION3, OPERATION4];
case RESOURCE2:
return [OPERATION1, OPERATION2, OPERATION3];
case RESOURCE3:
return [OPERATION1, OPERATION2];
default:
return [];
}
};
console.log (operationPerResource(ResourceTypes.RESOURCE2))
will compile 🥳 and output ["OPERATION1", "OPERATION2", "OPERATION3"]
👍
Upvotes: 2
Reputation: 113
EDIT: (I can't comment your post yet)
If you check in typescript playground you can see why it works with JS object dans not enum.
When you check RESOURCE1
it's not evaluated as the string RESOURCE1
you chan check that by changing RESOURCE1: 'RESOURCE123'
for exemple
I don't usually work with enum neither but seems that
const { RESOURCE1, RESOURCE2, RESOURCE3 } = ResourceTypes
// RESOURCE1 != 'RESOURCE1' as it would be for a JS Object
// RESOURCE1 === RESOURCE1
You can check this playground open your console, and hit run button.
If you look at cases keys, you'll see that the first one is not RESOURCE1aze
but still RESOURCE1
You could still use tell don't ask pattern to avoid switch statement :
import { RESOURCE1, RESOURCE2, RESOURCE3 } from '../enums/ResourceTypes'
import { OPERATION1, OPERATION2, OPERATION3, OPERATION4 } from '../enums/OperationTypes'
const cases = {
RESOURCE1: [OPERATION2, OPERATION3, OPERATION4],
RESOURCE2: [OPERATION1, OPERATION2, OPERATION3],
RESOURCE3: [OPERATION1, OPERATION2],
default: []
}
const operationPerResource = (resource: ResourceTypes): OperationTypes[] => {
const operations = cases[ressource] || cases['default']
return operations
}
export default operationPerResource
Here is an exemple in the typescript playground
Upvotes: 0
Reputation: 139
Can you show example calling code? A few thoughts that might help to track down the issue:
I would expect the signature to be
const operationPerResource = (resource: ResourceType): OperationTypes[]
This will guarantee you're calling with a ResourceType
I've never seen enums destructured like that. Of course I don't think there's anything wrong with it, but it's possible that TypeScript is doing something unexpected with the types. Does anything change if you rewrite out explicitly ResourceType.RESOURCE1
, etc.
Upvotes: 0