我可以编写一个非泛型类型防护,以检查给定的字符串是否是字符串枚举的成员,如下所示:
enum MyEnum {
Thing1 = 'thing one',
Thing2 = 'thing two',
}
const isMyEnum = (token: any): token is MyEnum => {
return Object.values(MyEnum).includes(token as MyEnum);
};
是否有可能使它通用,以便我可以对许多不同的字符串枚举重新使用相同的检查逻辑?
答案 0 :(得分:4)
TS字符串枚举和数字枚举具有完全不同的JS发出。
可接受的答案适用于OP的字符串枚举情况。
但是使用数字枚举的人可能会天真的认为它也适用于他们的用例。小心点。
//number enum here
enum E {
A,
B,
C,
}
const isSomeEnum = <T>(e: T) => (token: any): token is T[keyof T] =>
(Object as any).values(e).includes(token as T[keyof T]);
console.log(isSomeEnum(E)("A")); //expected false, actual true
console.log(isSomeEnum(E)(0)); //expected true , actual true
function isSomeEnum2<T> (e: T) : (token: unknown) => token is T[keyof T] {
const keys = Object.keys(e)
.filter((k) => {
return !/^\d/.test(k);
});
const values = keys.map((k) => {
return (e as any)[k];
});
return (token: unknown): token is T[keyof T] => {
return values.includes(token);
};
};
console.log(isSomeEnum2(E)("A")); //expected false, actual false
console.log(isSomeEnum2(E)(0)); //expected true , actual true
答案 1 :(得分:2)
您的意思是这样吗?
const isSomeEnum = <T>(e: T) => (token: any): token is T[keyof T] =>
Object.values(e).includes(token as T[keyof T]);
So isSomeEnum
从枚举对象生成类型保护函数。类型T[keyof T]
表示types of the property values of T
。
const isMyEnum = isSomeEnum(MyEnum);
// const isMyEnum: (token: any) => token is MyEnum
调用isSomeEnum(MyEnum)
时,类型T
被推断为typeof MyEnum
,然后T[keyof T]
是其属性值,即MyEnum
。
希望有帮助。祝你好运!
答案 2 :(得分:1)
@jcalz 答案之上的一个变体只是一个可以直接使用的简单函数:
const isEnumValue = <T extends { [k: string]: string }>(something: any, enumObject: T): something is T[keyof T] =>
typeof something === 'string' && Object.values(enumObject).includes(something);
正如 Justin AnyhowStep 所观察到的,此函数仅适用于字符串枚举,因此我放置了 T extends { [k: string]: string }
子句。这样我们就有了这种行为:
enum StringEnum {
A = 'aaa',
B = 'bbb',
}
enum NumberEnum {
A,
B,
}
let a;
if (isEnumValue(a, StringEnum)) {
if (a === 'SOMETHING') {
// compiler complains:
// This condition will always return 'false' since the types 'StringEnum' and '"SOMETHING"' have no overlap.
}
}
if (isEnumValue(a, NumberEnum)) {
// compiler complains:
// Argument of type 'typeof NumberEnum' is not assignable to parameter of type '{ [k: string]: string; }'.
// Property 'A' is incompatible with index signature.
// Type 'NumberEnum' is not assignable to type 'string'.
}