【问题标题】:Typescript can't infer inner type of Iterable of IterableTypescript 无法推断 Iterable 的内部类型
【发布时间】:2022-01-24 08:25:04
【问题描述】:

这是一个简单的函数,它接受一个 Iterable 的 Iterables。

function unwrapFirst<T extends Iterable<U>, U>(iter: Iterable<T>): U {
  return [...[...iter][0]][0];
}

unwrapFirst([[1,2,3],[4,5,6]]);

我希望 TypeScript 能够正确地将 U 的类型推断为 number,但它会将其推断为 unknown。有人可以解释为什么吗?以及如何让 TypeScript 正确推断 U

【问题讨论】:

  • 很奇怪,function unwrapFirst&lt;U&gt;(iter: Iterable&lt;U&gt;): U { return [...iter][0]; }; unwrapFirst([1,2,3]); 确实被正确推断为 function unwrapFirst&lt;number&gt;(iter: Iterable&lt;number&gt;): number,但 function unwrapFirst&lt;U, T extends Iterable&lt;U&gt;&gt;(iter: T): U { return [...iter][0]; }; unwrapFirst([1,2,3]); 没有,而是推断为 function unwrapFirst&lt;unknown, number[]&gt;(iter: number[]): unknown
  • 性能说明:您应该使用return iter[Symbol.iterator]().next().value[Symbol.iterator]().next().value; 作为函数体,以避免为了获得第一个值而迭代整个嵌套序列。

标签: typescript multidimensional-array nested typescript-generics type-inference


【解决方案1】:

Generic constraints 不用作推理站点。有关类似问题,请参阅 microsoft/TypeScript#44711

假设T 被限制为Iterable&lt;U&gt;,您大概期望编译器从T 推断出U。但这不会发生,因为约束不用作推理站点。所以为T推断的类型对U没有影响,因此U推​​断失败,编译器falls back to unknown

如果你想使用推理从T 得到U,你将只在T 中使函数泛型,然后通过conditional type inference 计算U。例如:

function unwrapFirst<T extends Iterable<any>>(
    iter: Iterable<T>
): T extends Iterable<infer U> ? U : never {
    return [...[...iter][0]][0];
}

const res = unwrapFirst([[1, 2, 3], [4, 5, 6]]);
// const res: number

看起来不错!

Playground link to code

【讨论】:

  • 伙计,我正在阅读你关于一个密切主题的旧答案 (stackoverflow.com/questions/61506176/…),我对你的知识印象深刻,感谢分享!
  • 我也印象深刻。我发誓,如果不是 jcalz 的回答,我想我还是会想办法系鞋带。
  • 有趣的是,更简单的版本unwrapFirst&lt;T&gt;(iter: Iterable&lt;Iterable&lt;T&gt;&gt;): T 不起作用,但它iter:T[][] 可以正确推断。甚至从number[][] 中提取Iterable&lt;Iterable&lt;infer U&gt;&gt; 也适用于条件类型。
猜你喜欢
  • 2020-11-01
  • 2020-09-02
  • 2018-07-03
  • 2019-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
相关资源
最近更新 更多