类型定义中使用泛型和条件时,Typescript不会推断switch语句中的类型

时间:2019-06-17 03:17:36

标签: typescript

我有一个函数的类型定义。我将第二个参数的类型定义为以第一个参数的类型为条件,例如:

const FOO = "FOO";
const BAR = "BAR";

let fooPayload = {
    zip: "zap"
}
let barPayload = {
    cat: "dog"
}

type ActionTypes = typeof FOO | typeof BAR;
interface MyFunction<T extends ActionTypes = ActionTypes> {
  (
    action: {
      type: T;
      payload: T extends typeof FOO
        ? typeof fooPayload
        : typeof barPayload;
    }
  ): boolean;
}

MyFunction接口所引用的函数中包含一个switch语句,该语句基于action.type进行切换,并根据情况对action.payload进行操作。这是一个示例:

const myFunction:MyFunction = (action) => {
    switch (action.type) {
        case FOO:
            action.payload.zip = "new zap"
            return true
        case BAR: 
            action.payload.cat = "new dog"
            return false
        default:
            return false
    }
}

我遇到的问题是Typescript无法正确地从switch语句推断出action.payload应该是什么。例如,如果action.type等于“ FOO”,则应该推断action.payload必须为typeof fooPayload。而是推断它是typeof fooPayload | typeof barPayload

这没有任何意义,因为action.payload的类型定义基于action.type的值,并且由于action.payload.zip在switch语句中被调用,因此只能在action.type等于“ FOO” 时发生,它应该推断出action.payload唯一可能的类型是typeof fooPayload

Here's a code example

我在这里做什么错了?

2 个答案:

答案 0 :(得分:0)

我不确定这是导致问题的确切位置,但总的来说,问题是您正在尝试重新发明哪种打字稿已经很好用,窄型联合。

条件是一个非常有趣的功能,但是由于它们是分布式的,因此有时会出现一些意外情况,因为它们超出了定义的范围。

我将以另一种方式实现这一点:

interface Action<T, P> {
    type: T,
    payload: P
}

type Actions 
    = Action<typeof FOO, typeof FooPayload> 
    | Action<typeof BAR, typeof BarPayload> 
    ;

interface MyFunction {
  (action: Actions): boolean;
}

不需要条件,并且打字稿将按预期在开关中缩小并集。

答案 1 :(得分:0)

您可以将类型显式传递给Assign语句:

    switch (action.type) {
        case FOO:
            (action.payload as typeof FooPayload).zip = "new zap"
            return true
        case BAR: 
            (action.payload as typeof BarPayload).cat = "new dog"
            return false
        default:
            return false
    }