take this enum for example
export enum MyEnum {
a = "a",
b = "b",
c = "c"
}
and then I define a function type where the parameter has to be one of these
i.e.
myFunction("c")
is fine
myFunction("d")
should throw an error
but obviously const myFunction = (param: string)
would not work here
but also const myFunction = (param: MyEnum)
does not work
CodePudding user response:
const f = (x: MyEnum) => …
…will work so long as you call f
like this:
f(MyEnum.a)
It is possible to "import" or alias the enumeration values:
const { a } = MyEnum;
f(a); // okay
const foo = MyEnum.b;
f(foo); // okay
If you wish to use strings, (e.g. f('a')
) you could use keyof typeof MyEnum
:
const f = (x: keyof typeof MyEnum) => …
f('a'); // okay
…but if this is what you want, you may want to consider defining a union type instead:
type MyEnum = 'a' | 'b' | 'c';
const f = (x: MyEnum) => …
f('a'); // okay
CodePudding user response:
You can use like below
export enum MyEnum {
a = "a",
b = "b",
c = "c"
}
const myFunction = (param: MyEnum) => {
console.log(param)
}
myFunction(MyEnum.a)
CodePudding user response:
You can try the following:
enum MyEnum {
a = "a",
b = "b",
c = "c"
}
const myFunction = (param:MyEnum) =>{
console.log(MyEnum[param]) //or MyEnym.param
}
myFunction("a") //will log a
myFunction("d") //will log undefined
CodePudding user response:
The supported use case for enums in TypeScript is when you want a set of named constants and you want to refer to them exclusively by name. If you find yourself wanting to deal with the values of these enums without the name, then enums are not a great fit. In the enum
enum MyEnum {
A = "a",
B = "b",
C = "c"
}
(I changed the keys because they are not in general identical to the values, but what follows is the same no matter what), it is intentionally forbidden for you to assign a string literal type like "a"
or "b"
to a value of the MyEnum
type:
let x: MyEnum;
x = MyEnum.A; // okay
x = "a"; // error! Type '"a"' is not assignable to type 'MyEnum'.
const myFunction = (x: MyEnum) => { }
myFunction(MyEnum.A); // okay
myFunction("a"); // error! Type '"a"' is not assignable to type 'MyEnum'.
Yes, at runtime, MyEnum.A
and "a"
are the same value, but the TypeScript compiler takes the position that you should never be referring to the value of an enum except through the enum object itself.
Instead of fighting with or working around this restriction, you can give up on enums and just use a plain object instead:
const MyEnum = {
A: "a",
B: "b",
C: "c"
} as const;
type MyEnum = typeof MyEnum[keyof typeof MyEnum];
//type MyEnum = "a" | "b" | "c"
let x: MyEnum;
x = MyEnum.A; // okay
x = "a"; // okay
const myFunction = (x: MyEnum) => { }
myFunction("a"); // okay
myFunction("z"); // error
Here we use a const
assertion to tell the compiler to keep track of the string literal values in the MyEnum
object. And now the MyEnum
object and associated MyEnum
type don't have any special enum branding to worry about. The type MyEnum
is just the union of string literals you care about. You can write MyEnum.A
if you want to, but you can also write "a"
; they are equivalent, both at runtime and in the type system.
Still, if you must use an enum, there is a way to use template literal types to widen an enum type to corresponding string literal values:
enum MyEnum {
A = "a",
B = "b",
C = "c"
}
type MyEnumStrings = `${MyEnum}`
// type MyEnumStrings = "a" | "b" | "c"
And then you can write your function in terms of that:
const myFunction = (x: MyEnumStrings) => { }
myFunction("a"); // okay
myFunction("z"); // error
But this doesn't work exactly for numeric enum values:
enum Whoops {
A = "a",
N = 123
}
type WhoopsStrings = `${Whoops}`
// type WhoopsStrings = "a" | "123"
And there won't be a way to do better until and unless something like microsoft/TypeScript#48094 is merged; this might happen for TypeScript 4.7, but I'm not sure.
Personally, I don't think it's worth this kind of hoop-jumping to get an off-label use of enums working, when you can just use a plain object instead. But that's up to you.