通用枚举类型保护

tuf*_*uff 8 typescript

我可以编写一个非泛型类型保护来检查给定的字符串是否是字符串枚举的成员,如下所示:

enum MyEnum {
  Thing1 = 'thing one',
  Thing2 = 'thing two',
}

const isMyEnum = (token: any): token is MyEnum => {
  return Object.values(MyEnum).includes(token as MyEnum);
};
Run Code Online (Sandbox Code Playgroud)

是否可以使其通用,以便我可以对许多不同的字符串枚举重复使用相同的检查逻辑?

jca*_*alz 16

你的意思是这样?

const isSomeEnum = <T>(e: T) => (token: any): token is T[keyof T] =>
    Object.values(e).includes(token as T[keyof T]);
Run Code Online (Sandbox Code Playgroud)

所以isSomeEnum从枚举对象产生类型保护函数。类型T[keyof T]表示 的属性值T类型

const isMyEnum = isSomeEnum(MyEnum);
// const isMyEnum: (token: any) => token is MyEnum
Run Code Online (Sandbox Code Playgroud)

当您调用 时isSomeEnum(MyEnum),类型T被推断为typeof MyEnum,然后T[keyof T]是它的属性值,即MyEnum

希望有帮助。祝你好运!

代码链接

  • 建议改进以避免使用任何安全类型 T: `const isSomeEnum = &lt;T extends { [s: string]:unknown }&gt;(e: T) =&gt; (token:unknown): token is T[keyof T] = &gt; Object.values(e).includes(token as T[keyof T]);` (2认同)

Jus*_*tep 5

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

Run Code Online (Sandbox Code Playgroud)

操场