【JavaScript】オブジェクト（連想配列）をObject.fromEntries()でmapする

# はじめに
オブジェクト（連想配列）をmapしたい場面があって調べたところ``Object.fromEntries()``に出会った。
実際に動作を確認しながら使ってみたのでそのメモ。

# 簡単なサンプル
シンプルなオブジェクトをmapしてみる。

```js
const obj = { a: 1, b: 2, c: 3 }

const convertedObj = Object.fromEntries(
  Object.entries(obj).map(([key, value]) => {
    console.log([key, value * 2])
    // コンソール出力
    // １回目： ["a", 2]
    // 2回目： ["b", 4]
    // 3回目： ["c", 6]
    
    return [key, value * 2]
  }),
)

console.log(convertedObj)
// コンソール出力
// {a: 2, b: 4, c: 6}
```
なるほど、``Object.fromEntries()``の返り値がしっかり連想配列で返ってきてる。

# 今回実装した内容
## 想定場面
``{ a: 数値、 b: "数値文字列", c: "日時（文字列）" }``見たいな感じの配列↓↓をAPIからレスポンスで受け取って

```ts
const objArr = [
  { a: 10, b: "10", c: "2021-09-01T06:38:19.274406Z" },
  { a: 20, b: "20", c: "2021-09-02T06:38:19.274406Z" },
  { a: 30, b: "30", c: "2021-09-03T06:38:19.274406Z" },
  { a: 40, b: "40", c: "2021-09-04T06:38:19.274406Z" },
  { a: 50, b: "50", c: "2021-09-05T06:38:19.274406Z" },
];
```

- ``a: 数値``はそのまま``number型``
- ``b: "数値文字列"``は``number型``にキャスト
- ``c: "日時"``はそのまま``string型``
こんな感じに↓↓整形したい場面があった。(普通はフロント側でこんな苦しい実装することも滅多にないと思いますが、、）

```ts
// 整形後（期待する結果）
[
{ a: 10, b: 10, c: "2021-09-01T06:38:19.274406Z" },
{ a: 20, b: 20, c: "2021-09-02T06:38:19.274406Z" },
{ a: 30, b: 30, c: "2021-09-03T06:38:19.274406Z" },
{ a: 40, b: 40, c: "2021-09-04T06:38:19.274406Z" },
{ a: 50, b: 50, c: "2021-09-05T06:38:19.274406Z" },
]
```

## 実装
冗長になってしまいました。でも、実現したいことはできた。

```ts
const objArr = [
  { a: 10, b: "10", c: "2021-09-01T06:38:19.274406Z" },
  { a: 20, b: "20", c: "2021-09-02T06:38:19.274406Z" },
  { a: 30, b: "30", c: "2021-09-03T06:38:19.274406Z" },
  { a: 40, b: "40", c: "2021-09-04T06:38:19.274406Z" },
  { a: 50, b: "50", c: "2021-09-05T06:38:19.274406Z" },
];

const convertedObjArr = objArr.map((obj) => {
  return Object.fromEntries(
    Object.entries(obj).map(([key, value]) => {
      // value を number型にキャストする
      const castedValue = Number(value);
      if (Number.isFinite(castedValue)) {
        console.log([key, castedValue]);
        // キャストに成功していれば、キャストした値をvalueとして返す
        return [key, castedValue];
      }
      console.log([key, value]);
      // キャストに失敗（NaN)すれば、そのままの値をvalueとして返す
      return [key, value];
    })
  );
});

console.log(convertedObjArr);
```

## コンソールを確認
map内の処理結果

```ts
// value を number型にキャストする
const castedValue = Number(value);
console.log(castedValue);
if (Number.isFinite(castedValue)) {
  console.log([key, castedValue]);
  // キャストに成功していれば、キャストした値をvalueとして返す
  return [key, castedValue];
}
console.log([key, value]);
// キャストに失敗すれば、そのままの値をvalueとして返す
return [key, value];
```
```
コンソール出力
["a", 10]
["b", 10]
["c", "2021-09-01T06:38:19.274406Z"]
["a", 20]
["b", 20]
["c", "2021-09-02T06:38:19.274406Z"]
["a", 30]
["b", 30]
["c", "2021-09-03T06:38:19.274406Z"]
["a", 40]
["b", 40]
["c", "2021-09-04T06:38:19.274406Z"]
["a", 50]
["b", 50]
["c", "2021-09-05T06:38:19.274406Z"]
```

最終的な整形後の結果

```ts
 console.log(convertedObjArr);
```
```
コンソール出力
[
{a: 10, b: 10, c: "2021-09-01T06:38:19.274406Z"},
{a: 20, b: 20, c: "2021-09-02T06:38:19.274406Z"},
{a: 30, b: 30, c: "2021-09-03T06:38:19.274406Z"},
{a: 40, b: 40, c: "2021-09-04T06:38:19.274406Z"},
{a: 50, b: 50, c: "2021-09-05T06:38:19.274406Z"},
]
```
ちゃんと期待する結果が出力されました。
実際の実装では``return Object.fromEntries(``以下を関数に切り出したものの、やはり冗長になってしまったので、もっと効率的な記述方法などあれば教えてください。


# 最後に
わかりやすい記事に非常に助けられました。
ありがとうございました。

- https://hfuji.hatenablog.jp/entry/2019/04/30/223722
- https://qiita.com/taku-0728/items/329e0bee1c49b7ce7cd1
- https://qiita.com/gp333/items/8bfa34979da64f15035c

JavaScript 面白い。