打字稿窄字符串类型是一个枚举的成员

Dan*_*515 8 enums typescript

我有一个接受字符串的函数,它应该调用另一个只接受两个枚举值的函数。

如何将字符串类型缩小为与枚举兼容的类型?我尝试使用 object.values 但打字稿似乎不喜欢我尝试的任何方式。

这是一个小例子

export enum A {
  a = "a",
  b = "b",
  c = "c",
}

export enum X {
  x = "x",
  y = "y",
  z = "z",
}

export const T = { ...A, ...X } as const;

function foo(t: string): X | A {
  if (Object.values(X).includes(t as X)) {
    return t
  }
  if(Object.values(A).includes(t)){
    return t
  }
  return X.x
}

Run Code Online (Sandbox Code Playgroud)

当然,我可以编写一个类型保护函数,但这对我来说只是作弊,因为我必须手动注意函数代码是否正确,并且它有效地正确地将字符串缩小到其中一个枚举中。所以这就是我想避免的:

function isXorA (t: string): t is X | A {
    if (Object.values(X).includes(t as X)) {
    return true
  }
  if(Object.values(A).includes(t as A)){
    return true
  }
  return false
}


function foo(t: string): X | A {
if(isXorA(t)){
  return t
}
  return X.x
}

Run Code Online (Sandbox Code Playgroud)

Cle*_*kel 2

今天在 ChatGPT 的帮助下,我编写了两个通用类型保护器,它们应该适用于任何枚举:

const isValueOfStringEnum = <T extends Record<string, string>>(enumType: T, value: string): value is T[keyof T] => 
   Object.values<string>(enumType).includes(value);
Run Code Online (Sandbox Code Playgroud)
const isValueOfNumericEnum = <T extends Record<string, number | string>>(enumType: T, value: number): value is Exclude<T[keyof T], string> => 
  (Object.values(enumType) as Array<number | string>).filter((v): v is number => typeof v === "number").includes(value);
Run Code Online (Sandbox Code Playgroud)

字符串和数字枚举的工作方式有点不同(反向映射),这就是数字变体有点复杂的原因。