【问题标题】:Type guards doesn't work when I use them with ReturnType in TypeScript当我在 TypeScript 中将它们与 ReturnType 一起使用时,类型保护不起作用
【发布时间】:2022-01-09 17:37:51
【问题描述】:

我有和枚举以及返回不同数据类型的两个函数:

enum Figure {
  Circle,
  Square,
}

const getCircle = () => ({
  figure: Figure.Circle,
  radius: 1
})

const getSquare = () => ({
  figure: Figure.Square,
  width: 1
})

我想要一个联合类型AnyFigure,这样我就可以组合使用圆形和正方形。我可以通过定义这两种类型来做到这一点:

type CircleType = {
  figure: Figure.Circle,
  radius: number
}

type SquareType = {
  figure: Figure.Square,
  width: number
}

type AnyFigure = CircleType | SquareType

// this throws compiler error because circles doesn't have width, which is great
const figure: AnyFigure = { figure: Figure.Circle, width: 4 }

这很好用,但我不想定义每个“get figure”函数的返回类型(因为在我的实际代码中,这些是我在 React 的 useReducer 钩子中使用的动作创建者,并且可能很少它们,每个都有不同的返回类型)。

因此我尝试使用 ReturnType:

type AnyFigureFromFuncs = ReturnType<typeof getCircle> | ReturnType<typeof getSquare>
// this doesn't throw compile errors, tested on TS 4.5.2
const figure: AnyFigureFromFuncs = { figure: Figure.Circle, width: 4 }

我在这里缺少什么?谢谢。

【问题讨论】:

    标签: javascript typescript types union-types


    【解决方案1】:

    您可以使用AnyFigure 作为返回类型。

    const getCircle = (): AnyFigure => ({
      figure: Figure.Circle,
      radius: 1
    })
    

    或者类型本身。

    const getCircle = (): CircleType => ({
      figure: Figure.Circle,
      radius: 1
    })
    

    【讨论】:

      【解决方案2】:

      如果您没有说明为什么您认为显式返回类型会导致减速器出现问题,那么很难以我确信满足您的标准的方式回答这个问题。减速器肯定是相当复杂的,但是合理的返回类型是类型安全的一部分,并且在区分中可能很重要。复杂、安全的程序根本不容易编写。

      正如问题所写,听起来您只是在问“我怎样才能使工厂函数具有一种返回类型(但不必每次都对其进行注释)?”如果那是情况下,那么您可以像这样使用工厂创建者:

      TS Playground link

      function createFigureFactory (figure: AnyFigure): () => AnyFigure {
        return () => figure;
      }
      
      const getCircle = createFigureFactory({
        figure: Figure.Circle,
        radius: 1,
      });
      
      const getSquare = createFigureFactory({
        figure: Figure.Square,
        width: 1,
      });
      
      // this is AnyFigure
      type AnyFigureFromFuncs = ReturnType<typeof getCircle> | ReturnType<typeof getSquare>;
      
      const figure: AnyFigureFromFuncs = { figure: Figure.Circle, width: 4 };
      /* Error:                                                   ^^^^^^^^
         Object literal may only specify known properties, and 'width' does not exist in type 'CircleType'.(2322) */
      

      【讨论】:

        【解决方案3】:

        你可以在枚举属性上使用as const

        enum Figure {
            Circle,
            Square,
          }
          
          const getCircle = () => ({
            figure: Figure.Circle as const,
            radius: 1
          })
          
          const getSquare = () => ({
            figure: Figure.Square as const,
            width: 1
          })
        
          type AnyFigureFromFuncs = ReturnType<typeof getCircle> | ReturnType<typeof getSquare>
        // this doesn't throw compile errors, tested on TS 4.5.2
        const figure: AnyFigureFromFuncs = { figure: Figure.Circle, width: 4 }
        

        【讨论】:

        • 好清晰的回答! :-)
        猜你喜欢
        • 2018-10-02
        • 2018-09-12
        • 2014-09-01
        • 1970-01-01
        • 2019-01-15
        • 2015-12-12
        • 2017-12-12
        • 2020-05-31
        • 1970-01-01
        相关资源
        最近更新 更多