Home > Mobile >  Typescript overloaded function with enum argument does not accept the union of enum values
Typescript overloaded function with enum argument does not accept the union of enum values

Time:10-26

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:

Typescript playground link

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)
}
  • Related