This is probably because of my misunderstanding of how enums work in Typescript but I find it very unintuitive nonetheless.
In a library I am using, there is an overloaded function with the exact same signature, the only difference is that the first signature uses one member of the enum type as argument, and the other one uses the other member.
I can't seem to call this function with union of the enum members. If I use the number literals of the enum members to call the function, it is fine. See simplified example here:
declare enum ArgType {
FIRST = 1,
SECOND = 2
}
declare function create(name: string, options: ArgType.FIRST): number;
declare function create(name: string, options: ArgType.SECOND): number;
//^^^^ Above is library code
//Below is me trying to use it
create("asd", ArgType.FIRST); //works
create("asd", ArgType.SECOND); //works
create("asd", Math.random() < 0.5 ? 1 : 2); //works
create("asd", Math.random() < 0.5 ? ArgType.FIRST : ArgType.SECOND); //ERROR
let one = ArgType.FIRST;
let two = ArgType.SECOND;
create("asd", Math.random() < 0.5 ? one : 2); //works
create("asd", Math.random() < 0.5 ? 1 : two); //works
create("asd", Math.random() < 0.5 ? one : two); //ERROR
Can someone please explain the behavior here and tell me how I can call this create function conditionally with either ArgType.FIRST
or ArgType.SECOND
without hardcoding the numbers at the call site?
CodePudding user response:
Your second parameter in that "error line" is:
Math.random() < 0.5 ? ArgType.FIRST : ArgType.SECOND
Typescript types that as ArgType
.
ArgType
is not a valid parameter for the defined create
function overloads.
You can work around that issue, by converting the argument to a Number
, or using an as
:
create("asd", Number(Math.random() < 0.5 ? ArgType.FIRST : ArgType.SECOND));
create("asd", (Math.random() < 0.5 ? ArgType.FIRST : ArgType.SECOND) as number);
That will force TS into interpreting the parameter as a value of that enum.
CodePudding user response:
If you can add another overload, you could add following and then it will accept a union type:
declare function create(name: string, options: ArgType.FIRST | ArgType.SECOND): number;
You could also wrap it into a custom function:
const wrappedCreate = (name: string, options: ArgType.FIRST | ArgType.SECOND) => {
return options === ArgType.FIRST ? create(name, options) : create(name, options)
}
wrappedCreate("asd", Math.random() < 0.5 ? ArgType.FIRST : ArgType.SECOND);
Or you may use typecasting instead of the ternary operator
const wrappedCreate = (name: string, options: ArgType.FIRST | ArgType.SECOND) {
return create(name, options as ArgType.FIRST)
}