2017-08-30 90 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