【问题标题】:Using conditional return type depending on boolean parameter根据布尔参数使用条件返回类型
【发布时间】:2019-05-02 22:29:18
【问题描述】:

我正在编写一个库,我想提供更准确的类型,这样库用户就不会在下面的示例中选择错误的类型。

如果参数convertJSONOutput 设置为true,则此方法返回IPlayerStatsIStatsItem[]

public async getStatsById(
    userId: string,
    timeWindow: TimeWindow = TimeWindow.Alltime,
    convertJSONOutput: boolean = true
  ): Promise<IPlayerStats | IStatsItem[]> {
  // Ommitted
}

问题:

我能否指定一个条件返回类型来指示将返回哪个接口(取决于convertJSONOutput 布尔参数)?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    根据布尔参数返回不同类型的最简单方法是重载:

    function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: true): Promise<IPlayerStats>;
    function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: false): Promise<IStatsItem[]>;
    function getStatsById(
        userId: string,
        timeWindow: TimeWindow = TimeWindow.Alltime,
        convertJSONOutput: boolean = true
      ): Promise<IPlayerStats | IStatsItem[]> {
    

    当您调用它时,然后根据参数的值推断缩小的类型:

    // Promise<IPlayerStats>
    const a = getStatsById('', undefined, true);
    
    // Promise<IStatsItem[]>
    const b = getStatsById('', undefined, false);
    

    重要的部分是每个重载都指定确切的文字值truefalse,而不是类型boolean。然后返回类型与此相关联。我已经强调了下面的关系。

    //                              **** =>        ************
    getStatsById(convertJSONOutput: true): Promise<IPlayerStats>;
    

    我稍微修改了代码,因此我可以创建一个独立的示例,它假定 TimeWindowIStatsItemIPlayerStats 已经定义:

    function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: true): Promise<IPlayerStats>;
    function getStatsById(userId: string, timeWindow: TimeWindow, convertJSONOutput: false): Promise<IStatsItem[]>;
    function getStatsById(
        userId: string,
        timeWindow: TimeWindow = TimeWindow.Alltime,
        convertJSONOutput: boolean = true
      ): Promise<IPlayerStats | IStatsItem[]> {
      // Ommitted
    }
    
    // Promise<IPlayerStats>
    const a = getStatsById('', undefined, true);
    
    // Promise<IStatsItem[]>
    const b = getStatsById('', undefined, false);
    

    【讨论】:

    • 有趣!我试过了,但现在在前两个函数重载中的 TimeWindow 参数上出现 TS 错误,上面写着 [ts] A parameter initializer is only allowed in a function or constructor implementation. 我假设我只需要在那里省略默认值吗?
    • 是的 - 您只需要 实现签名 上的默认值,而不需要重载签名上的默认值。您可以在重载时将参数设为可选。想象一下,一旦编译器使用它们来提取类型信息,重载就会被删除(因为它们是!) - 所以你不能在它们中有实际的逻辑。
    • 不幸的是,默认参数值不起作用:getStatsById('', null) // "Expected 3 arguments, but got 2"
    • 遗憾的是,传递函数变量也不起作用:function fn(convertJSONOutput: boolean = true) { return getStatsById('', null, convertJSONOutput); } // Argument of type 'boolean' is not assignable to parameter of type 'false'.
    • @Stiggler 转译后的输出发生了微妙的变化,所以它必须是 undefined 而不是 null。我会更新的。
    猜你喜欢
    • 2018-12-28
    • 2010-12-04
    • 2011-12-08
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 2013-11-29
    相关资源
    最近更新 更多