2017-08-30 87 views
1

我创建一个用户定义型保护,以确定是否(不安全)的字符串在运行时取出的是一个字符串enum的成员创建用户定义型保护试图编译上面的代码时,收到以下:无法为字符串枚举

[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,当我知道类型是至少string

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

是否有任何方式使用字符串在enum上执行方括号访问?

回答

2

当我有'没有隐含的任何'打开时,我会得到那个错误。我怀疑这可能是一个编译器问题。

它的工作原理,如果你只投xany

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 

我注意到,在这个功能的例子,他们要么具有相似的类型转换,否则该参数是any类型。

另请参阅here了解此问题的一些解释。

尽管如此,我仍然认为您需要决定是否要查找名称或值。根据您的实施情况,我认为您可能确实在寻找isVendorValue而不是isVendorName。 (我不认为它甚至有意义问,如果名字是一个Vendor,因为它不是,你要知道,如果该值是一个Vendor):

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

// doesn't make sense. the name cannot be a Vendor. 
const isVendorName = (name: string | Vendor): name is Vendor => { 
    return !!Vendor[<any>name]; 
}; 

// requires ES7, see below 
const isVendorValue = (value: string | Vendor): value is Vendor => { 
    return Object.values(Vendor).some((x: any) => x === value); 
}; 

console.info(isVendorName("A"));  // true 
console.info(isVendorName("a"));  // false 
console.info(isVendorName("C"));  // false 
console.info(isVendorName(Vendor.A)); // false 

console.info(isVendorValue("A"));  // false 
console.info(isVendorValue("a"));  // true 
console.info(isVendorValue("C"));  // false 
console.info(isVendorValue(Vendor.A)); // true 

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类型的反正。你说“我知道这个类型至少是string”,但这只是不必要地限制了这个方法用于测试字符串的用法。

而且您根本不知道这一点,具体取决于您在何处使用该方法。你知道的是,如果它不是一个字符串,那绝对不是Vendor

这个想法是,给定一些对象或值(不管是否为string),确定它是否为enum的成员,并且如果它是在类型系统中作为一个对待。更广泛适用的方法比不必要的狭义方法更好。

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

我的意图是有一个用户定义的类型后卫,而不是返回'boolean'的函数。您的示例不会将类型信息传递给编译器,它们仅返回true或false。这是只有用户定义的类型守卫才能完成的事情。 – Rick

+0

@Rick你期望'返回!!厂商[x]'除了'boolean'之外还要返回吗? K对不起,正在阅读这个概念... –

+0

用户定义的类型后卫返回布尔值,但它不仅仅是返回布尔值。请参阅:https://basarat.gitbooks.io/typescript/docs/types/typeGuard.html – Rick