I am writing a TypeScript library that uses enums, like this:
export enum Fruit {
// enum values must be integers,
// because the upstream library expects them that way.
Apple = 0,
Banana = 1,
}
/** A wrapper function for `upstreamLibrary.useFruit`. */
export function useFruit(fruit: Fruit) {
upstreamLibrary.useFruit(fruit as number);
// TODO: Do more stuff.
}
By default, the library ships with Apples and Bananas, but I want end-users to be able to create their own fruit. Right now, they can do that like the following:
import { useFruit } from "fruits";
enum FruitCustom {
// `upstreamLibrary.getFruitValue` returns an integer.
// It is guaranteed to never overlap with any other Fruit values.
Pear = upstreamLibrary.getFruitValue("Pear"),
}
useFruit(FruitCustom.Pear);
However, this will throw a compiler error, because FruitCustom does not match Fruit. So, in my library, I have to type the useFruit function like this:
export function useFruit(fruit: Fruit | number) {}
Unfortunately, Fruit | number resolves to just number, so now I've lost type safety, which sucks!
What's the best way to handle this?
Additional discussion: We can't use enum merging to solve this problem because you can only do that with local enums. Because Fruit comes from a 3rd party library, TypeScript won't let you do that.
Other requirements: If the solution involves not using enum, then it is necessary to be able to iterate over the members of the enum, like you can with normal enums.