返回所有可能的函数返回值的并集。

huangapple go评论69阅读模式
英文:

Return union of all possible function returns

问题

我想了解为什么这个代码会失败,编译器没有将A推断为类似于string[] | number[]的联合类型。而是将A推断为第一个返回值,即string[]。有没有办法修复这个问题?

const define = <A>({ handler }: { handler: (some: boolean) => A[] }) => ({ handler });
const a = define({
  handler: (some: boolean) => {
    if (some) {
      return ["foo", "bar"];
    } else {
      return [1, 2];
    }
  },
});

Plaxground

英文:

I would like to understand why this fails and the compiler does not infer A as a union like string[] | number[]. instead A is inferred as the first return value, in this case string[]. Is there a way to fix it?

const define = &lt;A&gt;({ handler }: { handler: (some: boolean) =&gt; A[] }) =&gt; ({ handler });
const a = define({
  handler: (some: boolean) =&gt; {
    if (some) {
      return [&quot;foo&quot;, &quot;bar&quot;];
    } else {
      return [1, 2];
    }
  },
});

Plaxground

答案1

得分: 0

这是因为当Typescript扫描你的代码时,它遇到了这个语句 -

if (some) {
  return ["foo", "bar"];
}

它会立即尝试推断泛型的类型,因为它是一个普通的泛型(没有任何约束),它将其确定为该类型。然后继续扫描,发现你返回了一个数字数组,于是它回到函数定义处检查泛型类型已经确定,并抛出一个错误。

你可以通过以下方式解决这个问题 -


const define = <A extends Array<unknown>,>({ handler }: { handler: (some: boolean) => A }) => ({ handler });

const a = define({
  handler: (some: boolean) => {
    if (some) {
      return ["foo", "bar"];
    } else {
      return [1, 2];
    }
  },
});

这是一个Playground链接

英文:

This happens because when Typescript is scanning your code, it comes across statement -

if (some) {
      return [&quot;foo&quot;, &quot;bar&quot;];
    }

And it goes ahead and tries to infer the type for the generic eagerly, because it's a plain generic (without any sort of constraint), it exacts it to that type, and when it continues to scan, it finds you returning a an array of numbers, so it goes back to check the function definition and sees that the generic type has already been determined, and throws an error.

You can overcome it like this -


const define = &lt;A extends Array&lt;unknown&gt;,&gt;({ handler }: { handler: (some: boolean) =&gt; A }) =&gt; ({ handler });

const a = define({
  handler: (some: boolean) =&gt; {
    if (some) {
      return [&quot;foo&quot;, &quot;bar&quot;];
    } else {
      return [1, 2];
    }
  },
});

Here's a Playground link.

huangapple
  • 本文由 发表于 2023年8月9日 14:48:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76865235.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定