JavaScript Tips | 配列ユーティリティ:型変換一括

JavaScript JavaScript
スポンサーリンク

テーマの整理:「型変換一括」とは何か

ここでの「型変換一括」は、配列の中のオブジェクトに対して「特定のプロパティの型をまとめて変換する」ユーティリティのことです。 業務だと、次のような場面でよく出てきます。

画面や CSV から来た値が全部文字列なので、数値や日付に直したい。 API から来た JSON のフィールドを、社内ロジックで扱いやすい型に揃えたい。 DB から読み出した値のうち、真偽値や数値をきちんと型変換しておきたい。

ポイントは、「1 件ずつ手作業で変換する」のではなく、“配列全体を一括で型変換する”ことです。

基本コンセプト:「型変換ルール」を決めて、配列全体に適用する

どんなデータに対して型変換するのか

よくある形は、こんなオブジェクト配列です。

const rawUsers = [
  { id: "1", age: "20", active: "true" },
  { id: "2", age: "35", active: "false" },
  { id: "3", age: null,  active: "true" },
];
JavaScript

ここから、次のようにしたくなります。

id は数値にしたい。 age も数値にしたい(null は 0 にしたいなど)。 active は真偽値にしたい。

この「どう変換するか」を「型変換ルール」として定義し、 それを配列全体に一括で適用するのが「型変換一括」です。

ユーティリティ 1:プロパティごとの変換関数をまとめて適用する

型変換ルールの定義

まず、「どのキーをどう変換するか」をオブジェクトで定義します。

const userTypeMap = {
  id:    (v) => Number(v),
  age:   (v) => (v == null ? 0 : Number(v)),
  active:(v) => v === true || v === "true",
};
JavaScript

ここでのポイントは、各キーに「変換関数」を割り当てていることです。 id は単純に Number。 age は null のときは 0、それ以外は Number。 active は真偽値 true か文字列 “true” のときに true、それ以外は false。

この「型変換ルール」を配列全体に適用するユーティリティを作ります。

実装:bulkConvertTypes

function bulkConvertTypes(records, typeMap) {
  if (!Array.isArray(records) || records.length === 0) {
    return [];
  }

  if (!typeMap || typeof typeMap !== "object") {
    return records.map((r) => ({ ...r }));
  }

  return records.map((record) => {
    const converted = { ...record };

    for (const key in typeMap) {
      if (Object.prototype.hasOwnProperty.call(record, key)) {
        const fn = typeMap[key];
        converted[key] = fn(record[key]);
      }
    }

    return converted;
  });
}
JavaScript

重要ポイントをかみ砕いて説明

まず「records が配列か」「空でないか」をチェックし、空なら空配列を返します。 typeMap がない場合は「型変換ルールがない」とみなして、単にコピーを返します。

各レコードについて、まず { ...record } でコピーを作ります(元データを壊さないため)。 typeMap のキーを順に見て、そのキーが record に存在する場合だけ変換関数を適用します。 変換結果は converted[key] に上書きし、最後に converted を返します。

これで、「指定したキーだけを、指定したルールで一括変換した配列」が手に入ります。

例題 1:ユーザー配列を一括型変換する

const rawUsers = [
  { id: "1", age: "20", active: "true" },
  { id: "2", age: "35", active: "false" },
  { id: "3", age: null,  active: "true" },
];

const userTypeMap = {
  id:    (v) => Number(v),
  age:   (v) => (v == null ? 0 : Number(v)),
  active:(v) => v === true || v === "true",
};

const normalizedUsers = bulkConvertTypes(rawUsers, userTypeMap);

console.log(normalizedUsers);
JavaScript

出力イメージはこうなります。

[
  { id: 1, age: 20, active: true },
  { id: 2, age: 35, active: false },
  { id: 3, age: 0,  active: true },
]
JavaScript

ここでのポイントは、

id が全部数値になっている。 age が全部数値になっていて、null は 0 に置き換えられている。 active が全部真偽値になっている。

というところです。

この「型変換済みの配列」を前提にすると、 後続の処理(集計・フィルタ・ソートなど)がかなり書きやすくなります。

ユーティリティ 2:型変換ルールを「型定義っぽく」まとめる

シナリオ

ユーザーだけでなく、売上データやログデータなど、複数の種類のレコードがある。 それぞれに「型変換ルール」を持たせたい。

型変換ルールをまとめる

例えば、こんな感じで「用途ごとの型変換ルール」をまとめておきます。

const TypeMaps = {
  user: {
    id:    (v) => Number(v),
    age:   (v) => (v == null ? 0 : Number(v)),
    active:(v) => v === true || v === "true",
  },
  sale: {
    id:      (v) => Number(v),
    date:    (v) => new Date(v),
    amount:  (v) => (v == null ? 0 : Number(v)),
    taxable: (v) => v === true || v === "true",
  },
};
JavaScript

使うときはこうです。

const normalizedUsers = bulkConvertTypes(rawUsers, TypeMaps.user);
const normalizedSales = bulkConvertTypes(rawSales, TypeMaps.sale);
JavaScript

ここでの重要ポイントは、「型変換ルールを一箇所にまとめている」ことです。 仕様変更(例: active の扱いを変える)があったときも、この TypeMaps を直せば全体に反映されます。 「このレコードはこういう型で扱う」という“型定義っぽいもの”をコードに持つイメージです。

ユーティリティ 3:型変換一括+配列正規化の組み合わせ

シナリオ

API から来るレスポンスが「配列のときもあれば単体オブジェクトのときもある」。 そのうえで、型変換もしたい。

toArray と組み合わせる

まず、前にやった toArray を使います。

function toArray(value) {
  if (value == null) return [];
  if (Array.isArray(value)) return value;
  return [value];
}
JavaScript

これを bulkConvertTypes と組み合わせます。

function normalizeWithTypes(value, typeMap) {
  const records = toArray(value);
  return bulkConvertTypes(records, typeMap);
}
JavaScript

使い方はこうです。

const responseA = [
  { id: "1", age: "20", active: "true" },
  { id: "2", age: "35", active: "false" },
];

const responseB = { id: "3", age: null, active: "true" };

const normalizedA = normalizeWithTypes(responseA, TypeMaps.user);
const normalizedB = normalizeWithTypes(responseB, TypeMaps.user);

console.log(normalizedA);
console.log(normalizedB);
JavaScript

ここでのポイントは、

「配列か単体か分からない入力」を、 まず配列に正規化し、 そのうえで型変換を一括で適用していることです。

入口でこの処理を通しておけば、 後続の処理は「必ず配列」「必ず型が揃っている」という前提で書けます。

型変換一括ユーティリティで意識してほしい重要ポイント

「型変換ルール」を明示的に持つ

型変換一括の肝は、「どのキーをどう変換するか」を明示的に持つことです。

id は Number。 amount は Number(null は 0)。 active は Boolean。 date は Date。

こういうルールを typeMap に閉じ込めておくと、

コードを読んだときに「このレコードはどういう型で扱われるのか」がすぐ分かる。 仕様変更があったときも、typeMap を直せばよい。

という状態になります。

初心者のうちは、まずは「数値」「真偽値」「日付」の 3 種類だけでもいいので、 型変換ルールを持つ感覚を身につけるとよいです。

「元データを壊さない」ことを徹底する

bulkConvertTypes では、必ず { ...record } でコピーを作ってから変換しています。 元のレコードを直接書き換えると、後続処理が「生データ」を必要とするときに困ります。

「入力はそのまま」「出力は型変換済み」という構造にしておくと、 デバッグや検証のときに「元の値」と「変換後の値」を比較しやすくなります。

手を動かして「型変換一括」の感覚をつかむ

次のコードを実行して、

生データ → 型変換一括 → 正規化済み配列 という流れを体感してみてください。

function bulkConvertTypes(records, typeMap) {
  if (!Array.isArray(records) || records.length === 0) {
    return [];
  }

  if (!typeMap || typeof typeMap !== "object") {
    return records.map((r) => ({ ...r }));
  }

  return records.map((record) => {
    const converted = { ...record };
    for (const key in typeMap) {
      if (Object.prototype.hasOwnProperty.call(record, key)) {
        const fn = typeMap[key];
        converted[key] = fn(record[key]);
      }
    }
    return converted;
  });
}

function toArray(value) {
  if (value == null) return [];
  if (Array.isArray(value)) return value;
  return [value];
}

function normalizeWithTypes(value, typeMap) {
  const records = toArray(value);
  return bulkConvertTypes(records, typeMap);
}

function demo() {
  const TypeMaps = {
    user: {
      id:    (v) => Number(v),
      age:   (v) => (v == null ? 0 : Number(v)),
      active:(v) => v === true || v === "true",
    },
  };

  const responseA = [
    { id: "1", age: "20", active: "true" },
    { id: "2", age: "35", active: "false" },
  ];

  const responseB = { id: "3", age: null, active: "true" };

  console.log("=== normalizedA ===");
  console.log(normalizeWithTypes(responseA, TypeMaps.user));

  console.log("=== normalizedB ===");
  console.log(normalizeWithTypes(responseB, TypeMaps.user));
}

demo();
JavaScript

まとめ:型変換一括ユーティリティで「文字列だらけの現実を、意味のある型に変える」

型変換一括は、 「現実のデータ(だいたい文字列)を、業務ロジックが扱いやすい“意味のある型”に一括で変換するためのユーティリティ」です。

プロジェクトに例えば次のような形で置いておくイメージです。

export function bulkConvertTypes(records, typeMap) { ... }
export function normalizeWithTypes(value, typeMap) { ... }
export const TypeMaps = { user: { ... }, sale: { ... } };
JavaScript

そして、

API 受信直後、 CSV/Excel 読み込み直後、 DB からの読み出し直後

など、「型がバラバラなデータが入ってくる入口」で必ずこの型変換一括を通す。

こう決めておくと、 後ろ側の処理は「型が揃った配列」を前提に書けるようになり、 コードが一気に読みやすく・壊れにくくなります。

“文字列だらけの現実”を、“意味のある型の世界”に連れてくる。 その橋渡しをしてくれるのが、型変換一括ユーティリティです。

タイトルとURLをコピーしました