打字稿模式与字符串文字类型的子类型匹配

时间:2016-12-29 14:09:57

标签: typescript pattern-matching

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函数中重复if,else语句。基本上我想基于'type'属性将字符串文字类型转换为适当的类型。我的尝试是这样做:

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

但是消息说:“p1”仅指一种类型,但在此处用作变量。

有办法做到这一点吗?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

不是一个确定的答案,但我不相信你可以。

FWIW建议的方法可能是a switch on the discriminating member

至于您的代码,您可能会忘记丢失类型信息的位置。 typeof运算符在这里没有意义。 typeof是一个运行时操作,即使您在运行时type: "LOAD_TODOS_ACTION"在代码中编写typeof x.type,也会返回string,我希望这对您没有帮助。字符串文字类型意味着唯一可接受的可分配值是该字符串,而不是引入新类型。

因此,为了实现您正在寻找的东西,我们需要能够获得接口成员的编译时类型信息。据我所知,没有办法做到这一点。当有一个,这是可能的,但在那之前我不相信它。