Typescript Can';t为字符串枚举创建用户定义的类型保护

Typescript Can';t为字符串枚举创建用户定义的类型保护,typescript,Typescript,我正在创建一个用户定义的类型保护,以确定在运行时获取的(不安全的)字符串是否是字符串enum的成员: enum Vendor { ACME = "Acme Co.", FOOBAR = "Foo Bar Industries" } export let isVendor = (x: string | Vendor): x is Vendor => { return !!Vendor[x]; }; 当我尝试编译上述代码时,我收到以下消息: [ts] Element impli

我正在创建一个用户定义的类型保护,以确定在运行时获取的(不安全的)字符串是否是字符串
enum
的成员:

enum Vendor {
  ACME = "Acme Co.",
  FOOBAR = "Foo Bar Industries"
}

export let isVendor = (x: string | Vendor): x is Vendor => {
  return !!Vendor[x];
};
当我尝试编译上述代码时,我收到以下消息:

[ts] Element implicitly has an 'any' type because expression is not of type 'number'.
(parameter) x: string
一种可能的修复方法如下:

export let isVendor = (x: any): x is Vendor => {
  return !!Vendor[x];
};
…但是当我知道类型至少是一个
字符串时,我宁愿避免使用
any

通过将
x
的类型签名更改为
number | string | Vendor
,我可以避免使用
any
,但这仍然不够理想


是否有任何方法可以使用字符串对
enum
执行方括号访问?

当打开“无隐式任何”时,我确实会遇到该错误。我怀疑这可能是编译器的问题

如果您只是将
x
强制转换为
any

enum Vendor {
   A = "a",
   B = "b"
}

const isVendor = (x: string | Vendor): x is Vendor => {
   return !!Vendor[<any>x];
};

console.info(isVendor("A")); // true
console.info(isVendor("a")); // false
console.info(isVendor("C")); // false
Object.values
显然是ES7,所以这里有一个替代实现。由于这些值在运行时不会更改,因此缓存这些值可能也会带来好处

const isVendorValue = (value: string | Vendor): value is Vendor => {
   return Object
      .keys(Vendor)
      .map((key: any) => Vendor[key])
      .some((x: any) => x === value);
};
我现在想到的另一件事是,与您的建议相反,参数实际上应该是
any
类型。您会说“我知道类型至少是一个
字符串
”,但这不必要地限制了该方法在测试字符串时的使用

你并不知道,这取决于你在哪里使用这种方法。您知道的是,如果它不是字符串,那么它肯定不是
供应商

其思想是,给定某个对象或值(
字符串
或非),确定它是否是此
枚举
的成员,然后将其视为类型系统中的成员。更广泛适用的方法比不必要的狭窄方法更好

const isVendorValue = (value: any): value is Vendor => {
   return typeof value === "string" &&
      Object
      .keys(Vendor)
      .map((key: any) => Vendor[key])
      .some((x: any) => x === value);
};

我的意图是拥有一个用户定义的类型保护,而不是一个返回
布尔值的函数。您的示例不向编译器传递类型信息,它们只返回true或false。这是只有用户定义的类型保护才能完成的。@Rick您希望
返回什么!!供应商[x]
除了返回
布尔值
?抱歉,我正在阅读这个概念…用户定义的类型guard返回boolean,但它不仅仅返回bool。见:
const isVendorValue = (value: any): value is Vendor => {
   return typeof value === "string" &&
      Object
      .keys(Vendor)
      .map((key: any) => Vendor[key])
      .some((x: any) => x === value);
};