【问题标题】:TypeScript and type-safe array.reduceTypeScript 和类型安全的 array.reduce
【发布时间】:2020-04-30 17:55:49
【问题描述】:

我正在使用 Array reduce 函数来创建数组的键控对象表示。我已经有了一个可行的解决方案,但注意到有多种方法可以确保输出对象是类型安全的。

鉴于我有以下接口和数组:

interface Meta {
  name: string;
  value: string;
}

const metaArr: Meta[] = [
  { name: 'a', value: 'hello' },
  { name: 'b', value: 'hi' }
];

在以下三种解决方案中,通常是首选它们中的任何一种,还是有更好的方法来做到这一点?

  1. 在声明reduce函数时使用Record
const metaObj = metaArr.reduce<Record<string, Meta>>((acc, curr) => {
  acc[curr.name] = curr;
  return acc;
}, {});
  1. 为初始对象声明映射到Meta接口的动态键:
const metaObj = metaArr.reduce((acc, curr) => {
  acc[curr.name] = curr;
  return acc;
}, {} as { [key: string]: Meta });
  1. 使用Record 转换初始对象:
const metaObj = metaArr.reduce((acc, curr) => {
  acc[curr.name] = curr;
  return acc;
}, {} as Record<string, Meta>);

提前致谢。

【问题讨论】:

  • 我会使用你的第一种方法。因为,按原样使用(至少在我看来)是一个可能的陷阱。因为它“覆盖”了类型系统。旁注:如果你仍然想使用 as cast,你应该使用 Record 东西。其他任何事情迟早都会落在你的脚下

标签: typescript


【解决方案1】:

虽然这可能是一个微不足道的例子,但仍有一些自以为是的考虑因素需要讨论。偏爱一种表示而不是另一种表示本质上是主观的。每个解决方案在功能上都实现了与任何其他解决方案完全相同的结果,并且每个解决方案的“可测试性”也是等效的。

因此,根据您的代码,为了帮助我做出类似决定,我可能会考虑以下几点:

  • reduce&lt;Record&lt;string, Meta&gt;&gt; 是您在阅读代码时首先看到的内容之一,并且在没有滚动可能较大的缩小投影的情况下,很明显它将产生的形状。
  • { [key: string]: Meta } 通常不如使用 Record&lt;T, R&gt; 的第一个点类型声明具有可读性,而且要实现相同的目标还需要编写更多内容
  • {} as Record&lt;string, Meta&gt;:使用as“断言”绝不是代码异味,但再次参考第一点,您的代码的读者将需要通过转到函数底部来查找reduce的结果类型

通常在面对这类问题时,条条大路通向您的代码的可读性。虽然可读性本质上也是一种主观追求,但通常越明确和包含的东西,就越容易推断出一段代码试图做什么。

【讨论】:

    猜你喜欢
    • 2018-09-09
    • 2021-06-01
    • 2021-03-16
    • 1970-01-01
    • 2019-05-26
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    相关资源
    最近更新 更多