【问题标题】:TypeScript: coerce generics T and UTypeScript:强制泛型 T 和 U
【发布时间】:2016-01-26 13:16:45
【问题描述】:

我正在用这个 API 编写一个库:

export var reduce = <T, U>(
  tArray: T[],
  tReducer: (current: U, tItem: T, index: number, tArray: T[]) => U,
  options: IChunkifyOptions = DEFAULT_OPTIONS,
  memo?: U
): Promise<U>

该实现与标准 JavaScript reduce 一样,如果未提供 memo,则使用 tArray 的第一项作为 memo

if (memo === undefined) {
  memo = tArray[0]; // Type 'T' is not assignable to Type 'U'
}

Casting (&lt;U&gt;) 合理地给出了Neither Type 'T' nor Type 'U' is assignable to the other.

定义 API 的合理方式是什么?

【问题讨论】:

  • 已回复here。先投到&lt;any&gt;
  • 谨慎使用&lt;any&gt; 转换。覆盖 TypeScript 的类型安全可能会导致许多无法预料的问题。我只在我的团队的测试模拟和存根中允许这样做,这是有充分理由的。在诉诸&lt;any&gt; 演员之前,请花点时间考虑以下答案。

标签: typescript typescript-generics


【解决方案1】:

问题在于T 不能分配给U,正如错误所解释的那样。这是纲要...

在您的示例中,如果未定义 memo,则将 memo 分配给 tArray 中的第一项

if (memo === undefined) {
  memo = tArray[0]; 
}

您已声明 memoU 并且您正试图为其分配 T 的值

T !== U,因此您会收到错误消息。

现在可能很想简单地使用memo = &lt;U&gt;&lt;any&gt;tArray[0] 投射它们,但问问自己“为什么需要这样做?”

memo 持有的意图是什么?当有人使用不同的对象时会发生什么?

reduce<Car, Watermelon>(...)

我怀疑你在这里有不同的意图。难道memo 真的应该是T | U 类型吗? T extend U

沿着&lt;U&gt;&lt;any&gt; 路径下去可能会导致许多意外的运行时错误,并且随着您的 API 增加而难以发现错误。我认为在使用&lt;U&gt;&lt;any&gt; 采取简单的方法之前,您需要再看看您想要的行为。

【讨论】:

  • 感谢您的建议。我之前尝试过extends,但是你不能在同一个“括号”中基于另一种类型来约束一个类型。我会更多地考虑这一点,但是当我使用导出的 API 时,无论是否提供 memo,编译器的行为似乎都符合预期。不过,我绝对不认为 TU 应该相互约束。
  • 那么我会推荐memo: T | U,因为这基本上就是您使用&lt;U&gt;&lt;any&gt; 所做的事情
猜你喜欢
  • 1970-01-01
  • 2020-12-06
  • 1970-01-01
  • 2019-09-28
  • 2019-01-26
  • 1970-01-01
  • 2020-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多