Among the numerous discussions on this topic, none seem to focus on developing a versatile function. This function should take an enum and a variable as input, check if the variable is part of that enum, and update the variable type if it is.
I have made progress with the following code:
// Function to check if the input is part of the enum
export function isEnumMember<T extends Record<string, K>, K>(value: unknown, enumType: T): value is K {
return (Object.values(enumType) as Array<unknown>).includes(value);
}
// Usage:
if(isEnumMember(var1, WORK_TYPE_ENUM)) {
// In here the type of var1 should be WORK_TYPE_ENUM
}
While this solution works, the variable var1
remains unknown
or its original type like string
even after the if
statement.
If I change the return type to T
, it doesn't work in this scenario (even when narrowing the enum to a string-valued one) (link to playground):
enum WORK_TYPE_ENUM { A = 'A', B = 'B' }
// Function to check if the input is part of the enum
export function isEnumMember<
T extends Record<string, unknown>
>(value: unknown, enumType: T): value is T {
return (Object.values(enumType)).includes(value);
}
// Usage:
const var1: string = 'A'
if (isEnumMember(var1, WORK_TYPE_ENUM)) {
/**
* This doesn't work,
* the type of var1 is 'string & typeof WORK_TYPE_ENUM',
* and we get the following error:
* Type '`prefix_${string & typeof WORK_TYPE_ENUM}`' is not assignable to type '"prefix_A" | "prefix_B"'.(2322)
* */
const foo1: `prefix_${WORK_TYPE_ENUM}` = `prefix_${var1}`
console.log(foo1);
// With the right type (simulated with `as`) - it does work
const foo2: `prefix_${WORK_TYPE_ENUM}` = `prefix_${var1 as WORK_TYPE_ENUM}`
console.log(foo2);
}