TypeScript / LESSON 03 / TS03

TypeScript:配列とオブジェクトの型

1学習の目的

2基礎解説

やりたいこと書き方意味
数値の配列const a: number[] = [1, 2]中身は全部数値
オブジェクト{ name: string; price: number }プロパティごとに型
オブジェクトの配列{ name: string }[]実務で最も多い形
変更禁止の配列readonly number[]push などができなくなる
✅ 覚えるべき重要ポイント
  1. 配列は「型名 + []」で表す。number[] は「数値だけが入る配列」。違う型を混ぜようとするとその場でエラーになる。
  2. オブジェクトの型は、プロパティ名と型を ; で区切って並べる{ name: string; price: number } のように書く。
  3. 定義していないプロパティにはアクセスできないproduct.pric のようなつづり間違いが、実行前にエラーとして分かる。JS07で undefined に悩まされた問題が、ここで解決する
  4. プロパティが足りなくてもエラーになる。必須の項目を書き忘れたまま実行してしまうことが無くなる。
  5. 実務で最も多いのはオブジェクトの配列{ name: string; price: number }[])。APIから受け取るデータも、この形がほとんど。

現場使用例:商品一覧、ユーザー情報、注文明細、APIレスポンス。「複数の項目を持つデータが、複数件ある」という構造は、あらゆるシステムの基本になる。

// 配列の型
const prices: number[] = [128000, 3200, 8500];
const names: string[] = ["ノートPC", "マウス"];

// ❌ 違う型は混ぜられない
const wrong: number[] = [1, "2"];
// → Type 'string' is not assignable to type 'number'.

// オブジェクトの型
const product: { name: string; price: number } = {
  name: "ノートPC",
  price: 128000,
};
console.log(product.name);

// ❌ 存在しないプロパティはエラー
console.log(product.stock);
// → Property 'stock' does not exist on type ...

// オブジェクトの配列(実務で最も多い形)
const items: { name: string; price: number }[] = [
  { name: "ノートPC", price: 128000 },
  { name: "マウス", price: 3200 },
];

// 配列のメソッドはJavaScriptと同じ(JS09)
const total: number = items.reduce((sum, i) => sum + i.price, 0);
console.log(total.toLocaleString());

// 変更を禁止する
const fixed: readonly number[] = [1, 2, 3];
// fixed.push(4);  → エラーになる

3基本ドリル(10問)

TS03-D01 数値の配列 [128000, 3200, 8500] を型注釈付きで宣言し、要素数を出力せよ。 コーディング★☆☆無料
期待される結果

出力 == 3

ヒント

const prices: number[] = [...] と書く。要素数は .length。

模範解答
const prices: number[] = [128000, 3200, 8500];

console.log(prices.length);
解説

配列の型は「中身の型 + []」。この配列には数値しか入らないことが、型として保証される。

TS03-D02 const a: number[] = [1, "2", 3]; と書くとどうなるか。
A. そのまま動く B. 実行前にエラーになる C. "2" が数値に変換される D. 実行時に落ちる
選択★☆☆無料
期待される結果

解答 == B

ヒント

number[] に文字列は含まれるか。

模範解答
B
解説

配列の中身も型チェックされる。JavaScriptなら何でも混ぜられるが、TypeScriptでは書いた時点で止められる。

TS03-D03 商品名と価格を持つオブジェクトを型注釈付きで宣言し(ノートPC・128000)、「ノートPC:128,000円」の形式で出力せよ。 コーディング★☆☆無料
期待される結果

出力 == ノートPC:128,000円

ヒント

{ name: string; price: number } という型を書く。プロパティは name.price ではなく product.name のように取り出す。

模範解答
const product: { name: string; price: number } = {
  name: "ノートPC",
  price: 128000,
};

console.log(`${product.name}:${product.price.toLocaleString()}円`);
解説

オブジェクトの型はプロパティごとに指定する。セミコロンで区切って並べるのが基本の書き方。

TS03-D04 文字列の配列を宣言するコードを完成させよ。 穴埋め★☆☆無料
コード
const names: ____ = ["A", "B", "C"];

console.log(names.join("/"));
期待される結果

出力 == A/B/C

ヒント

文字列の配列を表す型。string に角カッコを付ける。

模範解答
string[]
解説

Array<string> という書き方もあるが、実務では string[] のほうが一般的

TS03-D05 型に定義していないプロパティ(例:product.stock)にアクセスするとどうなるか。
A. undefined が返る B. 実行前にエラーになる C. null が返る D. 自動的に追加される
選択★☆☆無料
期待される結果

解答 == B

ヒント

型に無いものは存在しないと見なされる。

模範解答
B
解説

JavaScriptなら undefined が返って静かに壊れる場面(JS07)。TypeScriptは書いた時点で止めてくれるので、つづり間違いも即座に分かる。

TS03-D06 商品オブジェクトの配列(ノートPC/128000、マウス/3200)を型注釈付きで宣言し、価格の合計を「合計:131,200円」の形式で出力せよ。 コーディング★★☆無料
期待される結果

出力 == 合計:131,200円

ヒント

型は { name: string; price: number }[] と書く。合計は reduce(JS09)。

模範解答
const items: { name: string; price: number }[] = [
  { name: "ノートPC", price: 128000 },
  { name: "マウス", price: 3200 },
];

const total: number = items.reduce((sum, i) => sum + i.price, 0);

console.log(`合計:${total.toLocaleString()}円`);
解説

これが実務で最も多いデータ構造。型を付けておくと、i.price と書いた時点でエディタが候補を出してくれる。

TS03-D07 変更できない配列を宣言するコードを完成させよ。 穴埋め★★☆無料
コード
const fixed: ____ number[] = [1, 2, 3];

console.log(fixed.length);
期待される結果

出力 == 3

ヒント

「読み取り専用」を意味する8文字のキーワード。

模範解答
readonly
解説

readonly を付けると push や代入ができなくなる。設定値やマスタデータなど、途中で書き換わってほしくないデータに使う。

TS03-D08 { name: string; price: number } 型の変数に { name: "A" } だけを代入するとどうなるか。
A. price は undefined になる B. エラーになる C. price は 0 になる D. 問題ない
選択★★☆無料
期待される結果

解答 == B

ヒント

型で定義したプロパティは必須か。

模範解答
B
解説

定義したプロパティはすべて必須。書き忘れると実行前にエラーになる。「あってもなくてもよい」項目には別の書き方がある(TS08)。

TS03-D09 商品オブジェクトの配列(ノートPC/128000、マウス/3200、キーボード/8500)から、10000円以上の商品名だけを取り出し、カンマ区切りで出力せよ。 コーディング★★☆無料
期待される結果

出力 == ノートPC

ヒント

filter で絞り、map で名前を取り出す(JS09)。型は { name: string; price: number }[]。

模範解答
const items: { name: string; price: number }[] = [
  { name: "ノートPC", price: 128000 },
  { name: "マウス", price: 3200 },
  { name: "キーボード", price: 8500 },
];

const expensive: string[] = items
  .filter((i) => i.price >= 10000)
  .map((i) => i.name);

console.log(expensive.join(", "));
解説

filter と map の結果にも型が付くmap((i) => i.name) の結果は自動的に string[] と推論されるので、型注釈と食い違えばエラーになる。

TS03-D10 注文オブジェクト(id: 1、商品名の配列 ["ノートPC", "マウス"])を型注釈付きで宣言し、「注文1:2点」の形式で出力せよ。 コーディング★★☆無料
期待される結果

出力 == 注文1:2点

ヒント

型は { id: number; items: string[] } のように、配列を含めて書ける。

模範解答
const order: { id: number; items: string[] } = {
  id: 1,
  items: ["ノートPC", "マウス"],
};

console.log(`注文${order.id}:${order.items.length}点`);
解説

オブジェクトの中に配列を含められる。実務のデータは入れ子になっていることが多く、型もその構造をそのまま表現する。

4実践シナリオ(5問)

TS03-S01 【在庫一覧】商品名・価格・在庫を持つオブジェクトの配列(ノートPC/128000/5、マウス/3200/42、キーボード/8500/18)を型注釈付きで宣言し、各商品を「ノートPC:128,000円(在庫5個)」の形式で3行出力せよ。 コーディング★★☆無料
期待される結果

出力3行が完全一致

ヒント

3つのプロパティを持つ型を書き、forEach か for...of で回す。

模範解答
const items: { name: string; price: number; stock: number }[] = [
  { name: "ノートPC", price: 128000, stock: 5 },
  { name: "マウス", price: 3200, stock: 42 },
  { name: "キーボード", price: 8500, stock: 18 },
];

for (const item of items) {
  console.log(`${item.name}:${item.price.toLocaleString()}円(在庫${item.stock}個)`);
}
解説

ループの中でも型が効いているitem の型は自動的に推論されるので、item.stok のような打ち間違いはその場で赤線になる。

TS03-S02 【在庫金額の集計】上記と同じ商品配列から、在庫金額の合計(価格×在庫の総和)を「在庫総額:927,400円」の形式で出力せよ。 コーディング★★☆無料
期待される結果

出力 == 在庫総額:927,400円

ヒント

reduce で price * stock を足し込む。

模範解答
const items: { name: string; price: number; stock: number }[] = [
  { name: "ノートPC", price: 128000, stock: 5 },
  { name: "マウス", price: 3200, stock: 42 },
  { name: "キーボード", price: 8500, stock: 18 },
];

const totalValue: number = items.reduce(
  (sum, i) => sum + i.price * i.stock,
  0
);

console.log(`在庫総額:${totalValue.toLocaleString()}円`);
解説

reduce の初期値 0 が number なので、結果も number と推論される。型注釈と一致しなければエラーになるので、計算ミスに気づきやすい。

TS03-S03 【要発注リスト】上記と同じ商品配列から、在庫が20個未満の商品を抽出し、「要発注:ノートPC(5), キーボード(18)」の形式で出力せよ。 コーディング★★☆無料
期待される結果

出力 == 要発注:ノートPC(5), キーボード(18)

ヒント

filter で絞り、map で「名前(在庫)」の文字列を作って join する。

模範解答
const items: { name: string; price: number; stock: number }[] = [
  { name: "ノートPC", price: 128000, stock: 5 },
  { name: "マウス", price: 3200, stock: 42 },
  { name: "キーボード", price: 8500, stock: 18 },
];

const lowStock: string[] = items
  .filter((i) => i.stock < 20)
  .map((i) => `${i.name}(${i.stock})`);

console.log(`要発注:${lowStock.join(", ")}`);
解説

filter → map → join という流れは実務で頻出。途中の型が {...}[] から string[] へ変わっていく様子が、型注釈から読み取れる。

TS03-S04 【顧客と注文の入れ子】顧客オブジェクト(名前「田中商事」、エリア「東京」、注文の配列 [{商品:"ノートPC", 数量:2}, {商品:"マウス", 数量:5}])を型注釈付きで宣言し、次の3行を出力せよ。
「田中商事(東京)」
「ノートPC × 2」
「マウス × 5」
コーディング★★★無料
期待される結果

出力3行が完全一致

ヒント

型は { name: string; area: string; orders: { product: string; qty: number }[] } のように入れ子で書く。

模範解答
const customer: {
  name: string;
  area: string;
  orders: { product: string; qty: number }[];
} = {
  name: "田中商事",
  area: "東京",
  orders: [
    { product: "ノートPC", qty: 2 },
    { product: "マウス", qty: 5 },
  ],
};

console.log(`${customer.name}(${customer.area})`);

for (const order of customer.orders) {
  console.log(`${order.product} × ${order.qty}`);
}
解説

型は入れ子にできる。ただしこの書き方は長くなりすぎるのが弱点で、TS07で学ぶ type や interface を使うと、名前を付けて整理できる

TS03-S05 【売上ランキング】商品オブジェクトの配列(ノートPC/128000/3、マウス/3200/15、モニター/45000/1)から売上(価格×数量)を計算し、売上の多い順に「1位 ノートPC:384,000円」の形式で3行出力せよ。 コーディング★★★無料
期待される結果

出力3行が完全一致

ヒント

map で売上を含む新しい配列を作り、sort で並べ替える(JS06の比較関数に注意)。

模範解答
const items: { name: string; price: number; qty: number }[] = [
  { name: "ノートPC", price: 128000, qty: 3 },
  { name: "マウス", price: 3200, qty: 15 },
  { name: "モニター", price: 45000, qty: 1 },
];

const sales: { name: string; total: number }[] = items
  .map((i) => ({ name: i.name, total: i.price * i.qty }))
  .sort((a, b) => b.total - a.total);

sales.forEach((s, index) => {
  console.log(`${index + 1}位 ${s.name}:${s.total.toLocaleString()}円`);
});
解説

map で作った新しいオブジェクトの型も、型注釈と一致しなければエラーになる。(i) => ({ ... }) の丸カッコを忘れる罠(JS09)も、TypeScriptなら型が合わずに気づける。

5仕上げ課題

TS03-FINAL 【注文管理システム】商品マスタと注文データを型付きで扱い、集計レポートを出力せよ。

データ(すべて型注釈を付けて宣言すること)
products:商品の配列
 ・{ id: 1, name: "ノートPC", price: 128000 }
 ・{ id: 2, name: "マウス", price: 3200 }
 ・{ id: 3, name: "キーボード", price: 8500 }

orders:注文の配列
 ・{ productId: 1, qty: 2 }
 ・{ productId: 2, qty: 10 }
 ・{ productId: 3, qty: 3 }

処理
① 各注文について、商品マスタから対応する商品を探す(find を使う)
② 見つからない場合は「商品不明」として金額0で扱う
③ 明細を出力し、最後に合計を出す

期待される出力(4行)
ノートPC × 2 = 256,000円
マウス × 10 = 32,000円
キーボード × 3 = 25,500円
合計:313,500円
期待される結果

出力4行が完全一致

ヒント

find は見つからないと undefined を返すため、そのまま product.price と書くとエラーになる。三項演算子で「見つかった場合」と「見つからない場合」を分けて処理する。合計は各明細の金額を足し込む。

模範解答
const products: { id: number; name: string; price: number }[] = [
  { id: 1, name: "ノートPC", price: 128000 },
  { id: 2, name: "マウス", price: 3200 },
  { id: 3, name: "キーボード", price: 8500 },
];

const orders: { productId: number; qty: number }[] = [
  { productId: 1, qty: 2 },
  { productId: 2, qty: 10 },
  { productId: 3, qty: 3 },
];

let total: number = 0;

for (const order of orders) {
  const product = products.find((p) => p.id === order.productId);

  const productName: string = product ? product.name : "商品不明";
  const amount: number = product ? product.price * order.qty : 0;

  total += amount;

  console.log(`${productName} × ${order.qty} = ${amount.toLocaleString()}円`);
}

console.log(`合計:${total.toLocaleString()}円`);
解説

この課題の核心は find の戻り値だ。配列から条件に合う要素を探す find は、見つからない可能性があるため、戻り値の型は「商品 または undefined」になる。

だから product.price といきなり書くと、TypeScriptは 「undefined かもしれないものからプロパティを読もうとしている」とエラーを出す。JavaScriptなら実行して初めて Cannot read properties of undefined で落ちていた場面だ(JS07で何度も遭遇したはず)。

ここでは product ? … : … と三項演算子で場合分けすることで、TypeScriptに「undefined の場合はこう扱う」と伝えている。これを書かないとコンパイルが通らない——つまり、型システムが「例外処理を書き忘れること」自体を防いでいる

この「あるかもしれない・ないかもしれない」の扱いは、TypeScriptで最も重要なテーマのひとつだ。TS08とTS09で、より洗練された書き方を学んでいく。

次章では関数に型を付ける。引数と戻り値を明示することで、関数の使い方そのものが型として表現できるようになる。