【问题标题】:Typescript cannot destruct union type打字稿不能破坏联合类型
【发布时间】:2019-02-06 01:05:52
【问题描述】:

我有一个联合类型Actions,它是

type Actions = Readonly<{
    type: ActionTypes.LOAD_POST;
    payload: string;
}> | Readonly<{
    type: ActionTypes.LOAD_POST_FAIL;
    payload: string;
}> | Readonly<{
    type: ActionTypes.LOAD_POST_SUCCESS;
    payload: {
        url: string;
        post: Post;
    };
}>

(这是生成的类型,原来嵌套了多个类型和ReturnType。)ActionTypes是一个字符串枚举。

const postReducer = (state = initialPostState, action: Actions): PostState => {
  const { type, payload } = action;
  switch (action.type) {
    case ActionTypes.LOAD_POST_SUCCESS: {
      const { post } = action.payload; // No error
      return { ...state, loading: false, success: true, post };
    }
  }

  switch (type) {
    case ActionTypes.LOAD_POST: {
      return { ...state, loading: true };
    }
    case ActionTypes.LOAD_POST_SUCCESS: {
      // [ts] Type 'string | { url: string; post: IFullPost; }' has no property 'post' and no string index signature.
      const { post } = payload;
      return { ...state, loading: false, success: true, post };
    }
    case ActionTypes.LOAD_POST_FAIL: {
      return { ...state, loading: false, success: false, post: null };
    }
    default:
      return state;
  }
};

为什么第一个有效,第二个无效?

【问题讨论】:

    标签: typescript typescript-typings typescript2.0


    【解决方案1】:

    您必须打开action.type 才能使action.payload 在case 语句中更改其类型

    【讨论】:

      【解决方案2】:

      这是设计使然。这是一个非常简单的例子:

      type Actions =
          {
              type: 1,
              payload: string;
          } |
          {
              type: 2,
              payload: { a: string }
          }
      
      function r(action: Actions) {
          const { type } = action;
          switch (type) {
              case 2: {
                  // Type 'string | { a: string; }' has no property 'a' and no string index signature.
                  const { a } = action.payload;
              }
      
          }
      }
      

      当我们析构action 对象时:const { type, payload } = action; 我们会丢失被析构类型的耦合信息。在此之后,type 常量将具有 1 | 2 类型,payload 将具有 string | { a: string; },即每种类型都将基于 Actions 类型合并所有可能的选项。这就是为什么 TS 无法确定 payload 的确切类型的原因,因为在 switch 条件下,我们有绝对独立的变量。

      【讨论】:

        【解决方案3】:

        您正在经历 TypeScript 达到其类型推断的极限 type guards

        在您的非工作示例中,TypeScript 无法推断出关于已解构变量 payload 的任何内容,尽管它在技术上是可行的。 我猜类型守卫只适用于直接/字面上参与守卫表达式的对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-05-18
          • 2015-08-17
          • 2021-08-05
          • 2018-12-06
          • 2020-11-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多