【问题标题】:TypeScript generics will only infer union types in simple casesTypeScript 泛型只会在简单的情况下推断联合类型
【发布时间】:2019-09-16 09:28:46
【问题描述】:

这是一个代码示例:

declare function test_ok<T>(arr: T[]): T;
test_ok([1, 2, "hello"]); // OK
test_ok([[1], [2], ["hello"]]); // OK

// note the nested array signature
declare function test_err<T>(arr: T[][]): T;
test_err([[1], [2], ["hello"]]); // ERR type "string" is not assignable to type "number"
test_err<string | number>([[1], [2], ["hello"]]); // OK if generic is specified

在一般情况下,TypeScript 似乎能够在给定异构数组时推断出最佳常见类型(基本联合)。但是,如果您尝试将泛型的范围扩大到一个简单的数组(例如上面的嵌套数组),它就会放弃。我在其他情况下也发现了这一点(例如,泛型在函数的 返回类型之上的函数数组,而不是整个函数)。这是某种性能优化吗?

【问题讨论】:

  • 这也发生在任何深度为 2 或更多的属性上,而不仅仅是数组:declare function x&lt;T&gt;(a: { x: {y: T}, u: {v: T}}): void; x({x: {y: 1}, u: {v: ""}});
  • TypeScript 最擅长在给定该类型的值的情况下推断类型,而不是在给定某个 函数 的值的情况下推断类型。所以我会尝试declare function foo&lt;T extends any[][]&gt;(arr: T): T[number][number];...这是否符合您的用例?仍然不确定是否有官方答案可以解释为什么推理在两层深处“放弃”。可能是故意的,因为有时您希望这样的事情失败。
  • 看起来这可能是故意的,见related comment on microsoft/TypeScript#31617
  • @jcalz 感谢您的解决方法以及链接。如果您将其放入答案中,我会批准它。

标签: typescript


【解决方案1】:

我要说的是,这更像是故意捕捉错误,而不是性能优化。当尝试推断T 给定一组应该是T 类型的值时,您总是可以通过扩大T 以适应所有值来成功,但是不可能发现一个合理的错误,其中一个输入的值不正确。我认为这是语言设计者的判断,很可能任何启发式方法都会产生一些误报和一些误报。

GitHub 问题microsoft/TypeScript#31617 是一个类似的报告,其中用户希望从两个参数推断string | number,一个是string 类型,另一个是number 类型。来自语言维护者之一的response 是:

这是一种有意的权衡,以便泛型可以在您期望多个对象属于同一类型时捕获错误,这通常更常见。


那么,有什么办法呢?显然您可以手动将T 指定为string | number。否则,如果您希望您的函数是允许的并且从不抛出错误,您可以将T 设置为给定参数本身的类型。编译器在推断给定该类型的值的类型方面比给定该类型的某些 函数 的值时更加一致。所以我在这里的解决方法是数组:

declare function test_fixed<T extends any[][]>(arr: T): T[number][number];
const ret = test_fixed([[1], [2], ["hello"]]); // string | number

在这种情况下,T 被限制为双重嵌套数组,返回类型T[number][number] 是最内层数组的元素类型(如果你取T,并在number 索引,您将获得另一种数组类型...如果您在 number 索引处查找 that 的值,您将获得最里面的元素类型...T[number][number]。 )

好的,希望对您有所帮助。祝你好运!

Link to code

【讨论】:

    猜你喜欢
    • 2021-06-05
    • 2019-05-06
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 2019-04-10
    • 2017-10-04
    • 2018-07-26
    • 2019-02-13
    相关资源
    最近更新 更多