2016-12-29 77 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

相关问题