2016-12-29 5 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 
} 

上記の動作を期待しています。私は一般的な方法でこれをやりたいので、ifSomeType関数でelse文を繰り返す必要はありません。基本的には、文字列リテラル型を 'type'プロパティに基づいた適切な型に変換したいと考えています。私の試みは、これを行うことでした。文字列リテラルタイプのサブタイプと一致するtypescriptパターン

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はあなたには役に立たないと思います。文字列リテラルタイプは、受け入れ可能な唯一の代入可能な値がその文字列であり、新しいタイプが導入されているわけではないことを意味します。

あなたが探しているものを達成するためには、インターフェイスメンバーのコンパイル時のタイプ情報を取得する必要があります。私が知る限り、これを行う方法はありません。 1つがある場合、これは可能ですが、それまでは私はそれが信じられません。

+0

型の別名は、実行時に利用できないので、このようにそれを行うことはできません。 – MistyK

1

驚くべきことに答えは:何もしません。

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

基本的に、上記の署名を持つ関数が呼び出されると、typescriptは自動的に型に干渉します。

EDIT:

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

関連する問題