【问题标题】:Ternary return type inferred from parameter failure (Typescript)从参数失败推断出的三元返回类型(Typescript)
【发布时间】:2020-07-03 14:40:57
【问题描述】:

经过长时间阅读问题和查看文档后,我仍然需要帮助。 我的问题很简单。我想定义一个函数,当一个数组作为参数给出时返回一个数组,但 Typescript 从不让我返回想要的值。

我简化了我想在这里编写的函数,因为错误仍然相同。

function notWorkingTernary(val: number | number[]) : typeof val extends number[] ? string[] : string{
  if(Array.isArray(val)){
    return val.map(v=>String(v));
  }
  else{
    return String(val);
  }
}

此函数在第一次返回时出现以下错误(第 3 行): Type 'string[]' is not assignable to type 'string'.ts(2322)

我不明白为什么 Typescript 要我返回一个字符串类型,即使这里 val 的类型显然是一个数字数组。

如果我避免给出返回类型,那么返回类型总是字符串 | string[] 并且每次使用该函数时我都必须自己转换返回类型。

我在这里做错了什么?

【问题讨论】:

  • 仅供参考,您所说的“三元类型”被称为“conditional types”。如果您改用该术语,您将有更好的时间搜索答案/文档/问题。

标签: typescript type-inference ternary


【解决方案1】:

您想使用function signature overloading。在您的情况下,它应该如下所示:

function notWorkingTernary(val: number): string;
function notWorkingTernary(val: number[]): string[];

function notWorkingTernary(val: number | number[]): (string | string[]) {
  if(Array.isArray(val)){
    return val.map(v=>String(v));
  }
  else{
    return String(val);
  }
}

基本上,您有一个带有多个“类型重载”的函数,这些“类型重载”在运行时处理,并通过声明类型来保证运行时与类型兼容。

Typescript playground.

【讨论】:

    【解决方案2】:
    function notWorkingTernary<T extends number | number[]>(val: T): T extends number[] ? string[] : string{
      if(Array.isArray(val)){
        return val.map(v=>String(v)) as T extends number[] ? string[] : string;
      }
      else{
        return String(val) as T extends number[] ? string[] : string;
      }
    }
    

    也许有人知道摆脱as T extends number[] ? string[] : string的聪明方法?

    【讨论】:

    • 你可以通过重载来摆脱它,但在我看来这样做并没有更好的办法。两种方法都不是类型安全的;这是一个悬而未决的问题...见microsoft/TypeScript#33912
    猜你喜欢
    • 2018-12-13
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 2017-10-15
    • 2019-01-07
    • 2020-03-11
    相关资源
    最近更新 更多