TypeScriptのRecord型を完全攻略!マップ型でデータを整理する方法
生徒
「TypeScriptで、特定の名前と値をセットにして管理したいのですが、どうすればいいですか?」
先生
「それなら、Record型(レコード型)を使うのがおすすめですよ。特定のキーワードに対して、どんな種類のデータを入れるかをあらかじめ決めておくことができる便利な仕組みです。」
生徒
「Record型を使うと、どんなメリットがあるんでしょうか?」
先生
「入力ミスを防げたり、中身が何であるかを整理できたりします。初心者の方でも使いやすいように、基本的な使い方から丁寧に解説していきますね!」
1. TypeScriptのRecord型とは何か
プログラミングを始めたばかりの方にとって、データを整理して保存する方法を学ぶことはとても大切です。TypeScriptにはRecord型という、非常に便利な道具があります。これは、ある「キー(名前)」と「値(中身)」をペアにして、そのデータの形を定義するためのユーティリティ型と呼ばれるものです。
例えば、電話帳を想像してみてください。名前が「キー」で、電話番号が「値」になります。このように、特定の言葉に対して決まった種類のデータを割り当てたいときにRecord型が活躍します。これを専門用語ではマップ型と呼ぶこともあります。地図のように、ある場所(名前)から情報(値)にアクセスできるイメージですね。
TypeScriptを使う最大の理由は、型というルールを決めることで、間違いを事前に防ぐことです。Record型を使うことで、「この箱にはこの種類の名前と、この種類のデータしか入れません」という厳しいルールをコンピューターに伝えることができます。これにより、後からデータを追加したり変更したりするときに、うっかり間違ったデータを入れてしまうミスを劇的に減らすことができるのです。
2. 基本的な書き方と構文を覚えよう
Record型を使うときは、特定の書き方のルールがあります。難しい記号が出てきますが、一つずつ分解して説明するので安心してください。基本的には以下のような形で記述します。
Record<キーの型, 値の型>
この山括弧の中に、二つの情報を入れます。一つ目は「キー(名前)」として使いたいデータの種類、二つ目は「値(中身)」として使いたいデータの種類です。例えば、キーを文字列(string)にして、値を数値(number)にしたい場合は、Record<string, number>と書きます。これにより、「名前は文字で、中身は数字ですよ」という宣言になります。
プログラミング未経験の方は、「型」という言葉に馴染みがないかもしれませんが、これは情報の「種類」のことだと考えてください。文字、数字、正誤(はい・いいえ)など、コンピューターが理解しやすいように種類を分類しているのです。Record型はこの種類の組み合わせを簡単に作ることができる魔法のテンプレートのようなものです。
3. 文字列と数値を組み合わせた具体的な例
それでは、実際にプログラムのコードを書いてみましょう。まずは、果物の名前とその価格を管理するリストを作ってみます。ここでは、名前が文字列(string)で、価格が数値(number)になるように設定します。
// 果物の名前(文字)と価格(数字)をセットにする型を作ります
const fruitPrices: Record<string, number> = {
apple: 150,
banana: 100,
orange: 200
};
console.log(fruitPrices.apple);
実行結果は以下のようになります。
150
このコードでは、fruitPricesという変数に対して、キーが文字で値が数字であるというルールを適用しました。もし、ここで価格のところに「安い」という文字を入れてしまうと、TypeScriptが「ここは数字を入れる場所ですよ!」と赤線を引いて教えてくれます。これが型の力であり、プログラミング初心者が安心して開発を進められる理由です。パソコンの操作に慣れていなくても、このようにルールが決まっていると迷わずに済みます。
4. 決まったキーワードだけを使えるようにする方法
先ほどの例では、どんな文字列でもキーとして使えましたが、特定の名前だけしか使えないように制限することもできます。これを専門用語でUnion型(ユニオン型)の活用と言います。例えば、一週間の曜日だけを使いたい場合を考えてみましょう。
「月曜日」「火曜日」「水曜日」といった特定の言葉以外を拒否することで、より精度の高いデータ管理が可能になります。これにより、例えば「月曜び」といった入力ミスも防ぐことができます。
// 使える名前を限定します
type DayOfWeek = "Monday" | "Tuesday" | "Wednesday";
// 決められた曜日以外を使うとエラーになります
const schedules: Record<DayOfWeek, string> = {
Monday: "会議があります",
Tuesday: "プログラミングの学習をします",
Wednesday: "買い物に行きます"
};
console.log(schedules.Monday);
実行結果は以下のようになります。
会議があります
このように、あらかじめ使える名前を絞っておくことで、プログラムはより頑丈になります。初心者のうちは、タイピングミスでプログラムが動かなくなることがよくありますが、このRecord型とUnion型の組み合わせを使えば、入力中にパソコンが間違いを指摘してくれるため、スムーズに学習を進めることができます。これは、間違ったレールに電車が乗らないようにするガードレールの役割を果たしています。
5. 複雑なデータ構造を管理する
値の部分には、数字や文字だけでなく、もっと複雑な情報のまとまりを入れることもできます。これをオブジェクトと呼びます。例えば、ユーザーのIDをキーにして、その人の「名前」と「年齢」の両方を管理したい場合です。
情報を整理する際に、一箇所にまとめておくと後で探しやすくなります。Record型を使えば、どんなに複雑なデータでも、きれいに整列させた棚のように管理することができます。
// ユーザー情報の形を定義します
type UserInfo = {
name: string;
age: number;
};
// ID(文字)に対して、ユーザー情報をセットにします
const userList: Record<string, UserInfo> = {
"user-001": { name: "田中", age: 25 },
"user-002": { name: "佐藤", age: 30 }
};
console.log(userList["user-001"].name);
実行結果は以下のようになります。
田中
この例では、UserInfoという型をまず作り、それをRecord型の「値」の部分に指定しました。これにより、ID一つに対して名前と年齢という複数の情報が紐付けられます。パソコンのフォルダの中にファイルを整理して入れる感覚に似ていますね。必要なときに必要なIDを指定するだけで、中身の詳細を簡単に取り出すことができるようになります。大規模なプログラムになればなるほど、このような整理整頓が重要になってきます。
6. Mapped Typesとの関係性を知る
ここで少しだけ難しい話をしますが、Record型の裏側ではMapped Types(マップ型)という仕組みが動いています。これは、既存の型を元にして、新しい型を自動的に作り出す仕組みのことです。Record型は、この便利な仕組みを誰でも簡単に使えるようにパッケージ化したものだと考えてください。
Mapped Typesは、数学の集合のように、あるグループの要素すべてに対して同じ処理を適用して新しいグループを作るような動作をします。例えば、「すべての項目を読み取り専用にする」といった一括変換が得意です。Record型はこの応用例の一つで、指定したキーの集まりに対して共通の型を割り当てるという動作を行っています。初心者の段階では、Mapped Typesという名前だけ覚えておき、まずはRecord型を使いこなせるようになることを目標にしましょう。裏側の仕組みを完璧に理解しなくても、使い道さえわかれば十分に役立つツールになります。料理に例えるなら、電子レンジの内部構造はわからなくても、ボタンを押せば温まるという仕組みを知っていれば便利に使えるのと同じです。
7. 読み取り専用のマップを作る方法
一度決めたデータを、後から絶対に変えたくないという場面もあります。例えば、設定ファイルや変換表などです。そのようなときは、Record型と別の機能を組み合わせて、中身を書き換えられないように保護することができます。これをReadonly(リードオンリー)と呼びます。
間違えてデータを上書きしてしまうと、プログラム全体がおかしくなってしまうことがあります。特にチームで開発をしたり、長い間プログラムを書き続けたりしていると、過去に自分が決めたルールを忘れてしまうことがあります。そういった不注意による事故を防ぐために、鍵をかけておくことが大切です。
// 読み取り専用の記録を作ります
const settings: Readonly<Record<string, boolean>> = {
darkMode: true,
notifications: false
};
// 下記のように書き換えようとするとエラーになります
// settings.darkMode = false;
console.log(settings.darkMode);
実行結果は以下のようになります。
true
このコードでは、Readonlyという言葉でRecord型を包んでいます。これにより、後から値を変更しようとしても、TypeScriptが「これは変更できません!」とエラーを出して止めてくれます。初心者のうちは、意図しない変数の書き換えでバグ(プログラムの不具合)を出してしまいがちですが、このように型を使って制限をかけることで、より安全なコードを書く技術が身につきます。安全靴を履いて作業をするような、プログラミングにおける護身術とも言えますね。
8. Record型を使う時の注意点
とても便利なRecord型ですが、注意すべきポイントもあります。それは、存在しないキーにアクセスしようとしたときの挙動です。例えば、電話帳に載っていない人の番号を調べようとすると、当然ながら情報は手に入りません。
TypeScriptの標準的な設定では、Record型で定義した範囲外のキーにアクセスしようとしても、コードを書いている最中にはエラーが出ないことがあります。しかし、実際にプログラムを動かしたときには「何もない(undefined)」という結果が返ってきてしまい、それが原因でトラブルが起きることがあります。これを防ぐためには、アクセスする前にそのキーが本当に存在するかを確認するか、より厳格な設定を有効にする必要があります。パソコンの操作と同じで、ファイルを開く前に「そのファイルが本当にあるか」を確認する癖をつけるのが上達の近道です。また、あまりにも広範囲にstring型をキーとして使いすぎると、何でも入る代わりに何も守られない状態になってしまうため、できるだけ使う名前を絞り込む工夫をしましょう。
9. 他の型と組み合わせて応用する
Record型は、単体で使うだけでなく他の機能と組み合わせることでさらに強力になります。例えば、ウェブサイトのメニュー項目ごとにアイコンとリンク先を管理するようなケースです。プログラムの中では、繰り返しの作業を減らすことが美徳とされています。Record型を使えば、同じ形式のデータがたくさん並ぶ構造を非常にスッキリと記述できます。
このように情報を整理する力をつけると、複雑なウェブサイトの仕組みも少しずつ理解できるようになります。ボタンを押したら画面が変わる、ログインしたら自分の名前が出る、といった動作の裏側では、必ずと言っていいほどこうしたデータの管理が行われています。Record型はそのデータの地図を作るための、最も基本的で強力な道具なのです。最初は難しく感じるかもしれませんが、自分で実際にキーと値を決めてコードを書いてみることで、徐々にその便利さが実感できるはずです。まずは自分の好きなものをリストにすることから始めてみましょう。