2016-12-29 68 views
0
export interface Action{ 
    type: string; 
} 

    export interface LoadTodos { 
     type: "LOAD_TODOS_ACTION" 
    } 

    export interface AddTodo { 
     type: "ADD_TODO_ACTION", 
     todo: Todo 
    } 

export type KnownAction = LoadTodos | LoadTodosSuccess | AddTodo; 

function isSomeType<T extends KnownAction>(x: any): x is T { 
    return x && typeof (x.type) === "LOAD_TODOS_ACTION"; 
} 


let knownAction: actions.KnownAction = { type: "LOAD_TODOS_ACTION" }; 


if (isSomeType(knownAction)) { 
    let loadTodosAction = knownAction; // load Todos type 
} 

我在期待上面的行爲。我想以通用的方式做到這一點,所以我不想重複如果,isSomeType函數中的else語句。基本上我想根據'type'屬性將字符串文字類型轉換爲適當的類型。我的嘗試是這樣做的:與字符串文字類型的子類型匹配的手稿模式

function isSomeType<T extends Action>(x: any): x is T { 
    type p1 = T['type']; 
    return x && typeof (x.type) === p1; 
} 

但消息說''p1'只是指一種類型,但在這裏用作一個變量。

有沒有辦法做到這一點?

回答

0

不是一個明確的答案,但我不相信你可以。

FWIW推薦的方法可能是a switch on the discriminating member

至於你的代碼,你可能會失去跟蹤類型信息丟失的地方。 typeof運算符在這裏不會有意義。 typeof是一個運行時操作,即使您在運行時在代碼中編寫type: "LOAD_TODOS_ACTION"typeof x.type將返回string,我認爲這對您沒有任何幫助。字符串文字類型意味着唯一可接受的可賦值是該字符串,而不是引入新類型。

所以爲了實現你要找的東西,我們需要能夠獲得接口成員的編譯時類型信息。據我所知,沒有辦法做到這一點。當有一個,這是可能的,但在那之前我不相信它。

+0

這是不可能做到這一點這種方式,因爲類型別名不是在運行時可用。 – MistyK

1

令人驚訝的是答案是:什麼都不做。

function isSomeType<T extends KnownAction>(x: T):T { 
    return x; 
} 

基本上打字稿會自動干擾類型,每當函數與上述簽名被調用。

編輯:

let knownAction: actions.KnownAction = { type: "LOAD_TODOS_ACTION" }; // KnownAction type 
let knownAction2 = isSomeType(knownAction) // LoadTodosAction type 
+0

是不是總是微不足道的真實? – Paarth

+0

我不希望這種行爲。我有.NET背景,如果你傳遞一個KnownAction類型的對象,你會得到KnownAction的回報。在這裏你得到一個確切的子類型。 – MistyK

+0

所以這裏是我的困惑。最初你正在寫一些看起來像用戶定義的類型後衛。起初我不知道這不再是一名警衛。你在這裏真的什麼都不做。 – Paarth

相關問題