2016-04-25 23 views
3

我有一個簡單的聯合類型的字符串文字,需要檢查它的有效性,因爲FFI調用「正常」的Javascript。有沒有一種方法可以確保某個變量是運行時處的任何字符串的實例?沿着使用type在運行時檢查字符串文字聯合類型的有效性?

type MyStrings = "A" | "B" | "C"; 
MyStrings.isAssignable("A"); // true 
MyStrings.isAssignable("D"); // false 

回答

9

既然Typescript 2.1,你可以通過with the keyof operator

這個想法如下。由於字符串文字類型信息在運行時不可用,因此您將定義一個帶鍵的普通對象作爲字符串文字,然後創建該對象的鍵類型。

如下:

// Values of this dictionary are irrelevant 
const myStrings = { 
    A: "", 
    B: "" 
} 

type MyStrings = keyof typeof myStrings; 

isMyStrings(x: string): x is MyStrings { 
    myStrings.hasOwnProperty(x); 
} 

const a: string = "A"; 
if(isMyStrings(a)){ 
    // ... Use a as if it were typed MyString from assignment within this block: the TypeScript compiler trusts our duck typing! 
} 
1

東西線只是Type Aliasing和編譯,因爲那javascript代碼,它不會出現你不能真正做到:

MyStrings.isAssignable("A"); 

,你能做些什麼它:

type MyStrings = "A" | "B" | "C"; 

let myString: MyStrings = getString(); 
switch (myString) { 
    case "A": 
     ... 
     break; 

    case "B": 
     ... 
     break; 

    case "C": 
     ... 
     break; 

    default: 
     throw new Error("can only receive A, B or C") 
} 

至於你問有關isAssignable,您可以:

function isAssignable(str: MyStrings): boolean { 
    return str === "A" || str === "B" || str === "C"; 
} 
+1

這個工作,但休息一旦'MyStrings'而不更新對應的'isAssignable'功能擴展。我希望減輕體力負擔。 –

+2

你可以做的事情不多。正如我寫的,'type'部分是嚴格的打字稿,並且這些信息在生成的js文件中丟失。你可以使用'enum'而不是''''。 –

+2

如果您願意付出努力,您可以編寫一個工具來生成定義類型的TS代碼,以及運行時類型從其他數據源執行檢查的TS代碼。我已經研究過使用C#編寫REST API的代碼,並且我們將C#數據合約編譯成TS,既包括類型定義,也包括描述類型的運行時反觀對象字面值。可以理解的是,所有這些都超出了TS的範圍。 – Alan