简体   繁体   English

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

[英]Typescript pattern matching with subtype of string literal type

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
}

I'm expecting the behaviour above. 我期望上面的行为。 I want to do this in a generic way so I don't want to repeat if, else statement in isSomeType function.Basically I want to convert string literal type into appropriate type based on 'type' property. 我想以一种通用的方式做到这一点,所以我不想重复isSomeType函数中的else语句。基本上我想基于'type'属性将字符串文字类型转换为适当的类型。 My attempt was to do this: 我的尝试是这样做:

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

But the message says: 'p1' only refers to a type but is used as a variable here. 但是消息显示:“ p1”仅引用类型,但在此处用作变量。

Is there a way to do this? 有没有办法做到这一点?

Surprisingly the answer is: do nothing. 令人惊讶的答案是:什么也不做。

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

Basically typescript will interfere type automatically whenever function with the above signature is called. 基本上,只要调用具有上述签名的函数,打字稿就会自动干扰打字。

EDIT: 编辑:

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

Not a definitive answer, but I don't believe you can. 这不是一个明确的答案,但我不相信您可以。

FWIW the recommended approach would probably be a switch on the discriminating member . FWIW推荐的方法可能是更改区分成员

As for your code, you may be losing track of where type information is lost. 至于您的代码,您可能会丢失类型信息丢失的位置。 The typeof operator will not be meaningful here. typeof运算符在这里没有意义。 typeof is a runtime operation and even if you write type: "LOAD_TODOS_ACTION" in your code at runtime typeof x.type will return string which I expect is not helpful to you. typeof是一个运行时操作,即使您在运行时在代码中type: "LOAD_TODOS_ACTION"typeof x.type也将返回string ,我希望这对您没有帮助。 A string literal type means that the only acceptable assignable value is that string, not that a new type is introduced. 字符串文字类型意味着唯一可接受的可分配值是该字符串,而不是引入了新类型。

So in order to achieve what you're looking for we'd need to be able to get an interface member's compile time type information. 因此,为了实现您的期望,我们需要能够获取接口成员的编译时类型信息。 As far as I know, there is no way to do this. 据我所知,没有办法做到这一点。 When there is one, this is possible, but until then I don't believe it is. 如果有一个,这是可能的,但是直到那时我都不相信。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM