受保护的类型,仍然不可赋值

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

Guarded type, still not assignable

问题

我的输出类型取决于输入类型。我使用自定义守卫来保护输入,但仍然无法分配给声明的输出类型:

type InputType<Sub extends SubType> = { a: Sub, b: string }
type SubType = Sub1 | Sub2
type Sub1 = { a: string }
type Sub2 = { a: string, b: string }
type OutputType<Sub extends SubType> =
  Sub extends Sub2 ?
    { c: string, d: string } :
    { c: string }

function handle<Sub extends SubType>(mainType: InputType<Sub>): OutputType<Sub> {
  if (hasSub2(mainType)) {
    return {c: '', d: ''};
  } else {
    return {c: ''};
  }
}

function hasSub2(a: InputType<SubType>): a is InputType<Sub2> {
  return 'b' in a.a;
}

这里是 Playground

英文:

My out type depends on the input type. I'm guarding the input with custom guard, but it's still not assignable to declared output:

type InputType&lt;Sub extends SubType&gt; = { a: Sub, b: string }
type SubType = Sub1 | Sub2
type Sub1 = { a: string }
type Sub2 = { a: string, b: string }
type OutputType&lt;Sub extends SubType&gt; =
  Sub extends Sub2 ?
    { c: string, d: string } :
    { c: string }

function handle&lt;Sub extends SubType&gt;(mainType: InputType&lt;Sub&gt;): OutputType&lt;Sub&gt; {
  if (hasSub2(mainType)) {
    return {c: &#39;&#39;, d: &#39;&#39;};
  } else {
    return {c: &#39;&#39;};
  }
}

function hasSub2(a: InputType&lt;SubType&gt;): a is InputType&lt;Sub2&gt; {
  return &#39;b&#39; in a.a;
}

Here's a Playground

答案1

得分: 1

以下是翻译好的部分:

目前的 TypeScript 设计限制是函数返回表达式必须可分配给显式的未解决条件返回类型注释,控制流的缩小不会帮助解决这个问题(问题)。

handle 中的 {c: '', d: ''}{c: ''} 不能分配给未解决条件的返回类型 OutputType&lt;Sub&gt;。你可以采取以下措施:

  1. 将所有返回表达式强制转换为 OutputType&lt;Sub&gt;示例
  2. 创建一个单独的函数重载(示例

替代方案 2 的实现

function handle&lt;Sub extends SubType&gt;(mainType: InputType&lt;Sub&gt;): OutputType&lt;Sub&gt;
function handle(mainType: InputType&lt;SubType&gt;): OutputType&lt;SubType&gt; {
  if ('b' in mainType.a) {
    return { c: '', d: '' };
  } else {
    return { c: '' };
  }
}

const sub1Res = handle({ a: { a: "aa" }, b: "b" }) // {c: string; }
const sub2Res = handle({ a: { a: "aa", b: "ab" }, b: "b" }) // { c: string; d: string; }

这样,函数的调用方可以获得正确的返回类型,函数的实现方(调用方或实现方)现在也可以编译。

2: https://www.typescriptlang.org/play/#code/C4TwDgpgBAkgdmArsAKuCAeAyogRlCAD2AjgBMBnKHXNSAPigF4oBvKAQwC5q8AaKLh4VgAJwCWcAOZQAvgFgAUKEi9a6ZmoCMUAD5qATEpXQaOlu25QRE6XOMaaBzZeFjJUgUOvu7C5RoA8shIqOjYeATEpJRqdBCMTEpQalEk5FROUAD8ySlsUADGbraeUGQlHnJQXHkp7MU+pfaKSgBmiHCFwOIA9nBQABYc5AA2mDRpMZl48fQAFAC2HJLxPPCh8RG49ACUPMHAm+E0jKx54m1Q88MUTksrcPG7u2x1UKIQwIiiA6yNAHIAQIKlAgbJOFRDsdINt6ABuPIQiCjCjQc6KfIfL4-P6AgEQjhQkLILanRGYlr+dqdbp9Aa3e5WDakk6zdB7HgcKDiKgssKwpxnPKfb6-MG4AE8gYcAB0HAp-iAA 3: https://www.typescriptlang.org/play/?ssl=17&amp;ssc=2&amp;pln=10&amp;pc=1#code/C4TwDgpgBAkgdmArsAKuCAeAyogRlCAD2AjgBMBnKHXNSAPigF4oBvKAQwC5q8AaKLh4VgAJwCWcAOZQAvgFgAUKEi9a6ZmoCMUAD5qATEpXQaOlu25QRE6XOMaaBzZeFjJUgUOvu7C5RoA8shIqOjYeATEpJRqdBCMTEpQalEk5FROUAD8yWxQAMZutp5QZMUeclBceexFPiX2ikoAZohwBcDiAPZwUAAWHOQANpg0aTGZePH0ABQAthyS8TzwofERuPQAlDzBwOvhNPSt7Z09fYMjEAtLcCuwCMgbNDO7UPuHkJszbHniLSgswA5LhgVBJFBFst0AA6DjbP6KFIpUQQYCIUR9Oo8YHAgTlKB4uQAbjysgIwwo0FYeVR6Mx2MKuPBsjJyKa-iUBV6ImseC0ACUIFQWFcyKNZq58lYAEQcDiyuReHiy3BK2SIgD0WrY9RsHhJTR5cD5FDwBmFooGQwlN2l0vlipVUHl6uVglV7s1UB1+X1vikRsJBukRtkQA

英文:

A current TS design limitation is that function return expressions must be assignable to the explicit unresolved conditional return type annotation, narrowing with the control flow doesn't help (issue).

{c: &#39;&#39;, d: &#39;&#39;} and {c: &#39;&#39;} in handle are not assignable to the unresolved conditional return type OutputType&lt;Sub&gt;. You can do the following:

  1. cast all return expressions to OutputType&lt;Sub&gt; (sample)
  2. create a separate function overload (sample)

Implementation of alternative 2

function handle&lt;Sub extends SubType&gt;(mainType: InputType&lt;Sub&gt;): OutputType&lt;Sub&gt;
function handle(mainType: InputType&lt;SubType&gt;): OutputType&lt;SubType&gt; {
  if (&#39;b&#39; in mainType.a) {
    return { c: &#39;&#39;, d: &#39;&#39; };
  } else {
    return { c: &#39;&#39; };
  }
}

const sub1Res = handle({ a: { a: &quot;aa&quot; }, b: &quot;b&quot; }) // {c: string; }
const sub2Res = handle({ a: { a: &quot;aa&quot;, b: &quot;ab&quot; }, b: &quot;b&quot; }) // { c: string; d: string; }

This way, the caller of the function gets the right return type and also the body of the function (callee or implementation side) compiles now.

huangapple
  • 本文由 发表于 2020年1月6日 19:58:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/59611715.html
匿名

发表评论

匿名网友

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

确定