TypeScriptを書いていて「オブジェクトの型ってどう書くんだっけ?」と手が止まった経験はありませんか。

objectObject{}、どれを使えばいいの?見た目が似ていて区別がつかない…
プロパティが3つあるオブジェクトの型って、どう書くのが正解なんだろう?
{ [key: string]: string }みたいな書き方、見たことはあるけど使い方がわからない…

TypeScriptのobject型まわりは、似た名前の型がいくつもあって最初は混乱しがちです。この記事では、オブジェクトの型をめぐって初学者がつまずきやすいポイントを順番に整理しながら、実務でそのまま使える書き方を実例コードで解説します。

この記事は次のような方におすすめです。

この記事はこんな人におすすめ!
  • object型・Object型・{}型の違いをきちんと整理したい方
  • プロパティを持つオブジェクトの型注釈の書き方を知りたい方
  • インデックスシグネチャや辞書のような型定義を学びたい方
  • typeinterfaceのどちらでオブジェクト型を書くべきか入口だけでも知りたい方

読み終えるころには、オブジェクトの型を見て迷うことが減り、自分のコードに自信を持って型を付けられるようになります。先に結論だけ言ってしまうと、迷ったらobject型単体ではなく、プロパティを書いたオブジェクト型を使えばOKです。

それでは、順を追って詳しく見ていきましょう!

まずは動画解説を観る

Contents
  1. TypeScriptで「オブジェクトの型」と言ったときの3つの意味
  2. object型・Object型・{}型の違いを整理する
  3. プロパティを持つオブジェクト型の書き方
  4. type・interfaceで名前を付けたオブジェクト型を定義する
  5. インデックスシグネチャでキーが動的なオブジェクト型を表す
  6. オブジェクト型でよくある落とし穴と書き方のコツ
  7. オブジェクト型まわりで関連する話題への入口
  8. よくある質問
  9. まとめ

TypeScriptで「オブジェクトの型」と言ったときの3つの意味

TypeScriptで「オブジェクトの型」という言葉が出てきたとき、実は文脈によって指しているものが3つに分かれます。ここを最初に整理しておくと、この後の解説がぐっと読みやすくなります。

3つの意味とは、次の通りです。

表記 何を表す型か 実務での使用頻度
object プリミティブ以外のあらゆる値を表す型(小文字) ほぼ無し
{ name: string } のような形 プロパティと型のペアで構造を定義した型 非常に高い
Object JavaScript組み込みのObject型(大文字) ほぼ無し

3つの違いをコードで眺めてみましょう。

// (1) プリミティブ以外を表す object 型
let value1: object = { name: "Alice" };

// (2) プロパティを定義した独自のオブジェクト型
let value2: { name: string } = { name: "Bob" };

// (3) JavaScript のグローバル Object 型
let value3: Object = { name: "Carol" };

ぱっと見はどれも似たオブジェクトを入れているだけですが、それぞれの型が許容する値の範囲はまったく違います。実務で日常的に使うのは(2)のプロパティを定義したオブジェクト型で、(1)と(3)は「違いを知っておく」程度で十分です。

この記事ではまず3つの違いを丁寧に整理し、その後でメインの「(2) プロパティを定義したオブジェクト型」の書き方を詳しく解説していきます。

object型・Object型・{}型の違いを整理する

ここからは3つの型をひとつずつ見ていきます。それぞれ「何が代入できて、何が代入できないか」を意識すると違いがクリアになります。

なお、TypeScriptの型はあくまでコンパイル時にチェックされるもので、実行時のJavaScriptには型情報が残らない点はおさえておきましょう。

object型|プリミティブ以外を表す

object型(小文字)は、プリミティブ型ではないあらゆる値を表す型です。プリミティブ型とは、stringnumberbooleanbigintsymbolnullundefinedの7つを指します。

つまりobject型には、これら以外のオブジェクト・配列・関数などが代入できます。

let obj: object;

obj = { name: "Alice" }; // OK:オブジェクト
obj = [1, 2, 3];          // OK:配列もオブジェクト
obj = () => 42;           // OK:関数もオブジェクト

obj = "hello"; // エラー:string はプリミティブ
obj = 123;     // エラー:number はプリミティブ
obj = null;    // エラー:null はプリミティブ

// プロパティアクセスはできない
const user: object = { name: "Alice" };
console.log(user.name); // エラー:プロパティ 'name' は型 'object' に存在しません

このコードのポイントは次の通りです。

  • object型は「何かしらのオブジェクトであること」しか保証しない
  • 配列も関数もJavaScript上はオブジェクトの一種なので、object型に代入できる
  • プロパティ構造は何も保証されないため、obj.nameのようなアクセスは型エラーになる

そのため、「中身が決まっているオブジェクトを受け取りたい」という用途にはobject型は不向きです。実務ではobject型単体を型注釈に使う場面はほぼありません。

なかむぅ
なかむぅ
プリミティブ型の全体像をきちんと押さえておきたい方は、こちらの記事もどうぞ。
【TypeScript】プリミティブ型ってなに?5つの基本型をわかりやすく解説
【TypeScript】プリミティブ型ってなに?5つの基本型をわかりやすく解説TypeScript初心者向けにプリミティブ型をやさしく解説。string・number・boolean・null・undefinedの基本と書き方がすぐわかります。...

Object型|JavaScriptのグローバルObject

Object型(大文字始まり)は、JavaScriptに組み込まれているグローバルなObject型を指します。Object.prototypeを継承するすべての値が代入可能で、結果としてnullundefined以外のほぼ何でも代入できてしまう型になります。

let value: Object;

value = { name: "Alice" }; // OK
value = "hello";            // OK:string も Object として扱える
value = 123;                // OK:number も同様
value = true;               // OK:boolean も同様
value = [1, 2, 3];          // OK
value = () => 42;           // OK

value = null;      // エラー
value = undefined; // エラー

このコードのポイントは次の通りです。

  • Object型はJavaScriptの組み込み型であり、ほぼあらゆる値を許容する
  • 「広すぎる型」のため、TypeScriptで型注釈に使う場面は実務ではまずない
  • object(小文字)とObject(大文字)はまったく別物として区別する必要がある

「型を付けたつもりが、何でも入る型になっていた」というミスを避けるためにも、Objectは実務で使わないと割り切ってしまって構いません。

{}型|空オブジェクトのリテラル型

{}は見た目から「空のオブジェクトしか入らない型」と誤解されがちですが、実態はObject型とほぼ同じで、nullundefined以外なら何でも代入できる型です。

let value: {};

value = { name: "Alice" }; // OK
value = "hello";            // OK:string も通る
value = 123;                // OK
value = true;               // OK
value = [1, 2, 3];          // OK

value = null;      // エラー
value = undefined; // エラー

このコードのポイントは次の通りです。

  • {}型は「プロパティの要件がない」型と解釈されるため、プリミティブも含めて広く代入を受け付ける
  • 「空オブジェクトに限定する型」ではない点が一番の落とし穴
  • Object型と同様、ターゲットの型注釈として実務で使うことは推奨されない

nullundefinedの挙動も含めて把握しておきたい方は、別記事も参考になります。

なかむぅ
なかむぅ
nullとundefinedの違いはオブジェクト型まわりでも頻繁に登場するので、押さえておくと役立ちます。
【TypeScript】nullとundefinedの違いは?使い分けと安全に扱う方法
【TypeScript】nullとundefinedの違いは?使い分けと安全に扱う方法TypeScriptのnullとundefinedの違いを初心者向けに解説。使い分け方や型の書き方、エラーを防ぐ安全な扱い方までわかりやすく学べます。 ...

3つの違いを比較表で整理

ここまでの内容を1枚の表にまとめます。

観点 object Object {}
プリミティブ(string/numberなど)の代入 エラー OK OK
nullundefinedの代入 エラー エラー エラー
オブジェクト・配列・関数の代入 OK OK OK
プロパティアクセスの可否 不可 不可(一部メソッドのみ) 不可(一部メソッドのみ)
実務での使いどころ ほぼ無し ほぼ無し ほぼ無し

まずはこう覚えればOKです。「3つとも実務ではほぼ使わない。プロパティを持つオブジェクトなら、その形を書いた独自のオブジェクト型を使うのが正解」。次の章から、その「独自のオブジェクト型」の書き方を詳しく見ていきます。

プロパティを持つオブジェクト型の書き方

ここからが本題です。実務で日常的に使うのは、プロパティ名と型をペアで指定する形のオブジェクト型注釈です。書き方はJavaScriptのオブジェクトリテラルとよく似ています。

TypeScriptの型注釈はあくまでコンパイル時のチェックに使われるもので、トランスパイル後のJavaScriptには残りません。つまり実行時には「namestringであるべき」といった制約は消えます。実行時にも値の形を検査したい場合は、別途バリデーションのロジックが必要になる、という前提を覚えておきましょう。

基本の書き方|キーと型のペアを並べる

最も基本的な書き方は、プロパティ名と型をコロンで区切って、{}の中に並べる形です。

const user: { name: string; age: number } = {
  name: "Alice",
  age: 30,
};

console.log(user.name); // "Alice"
console.log(user.age);  // 30

このコードのポイントは次の通りです。

  • { プロパティ名: 型; ... }の形で、JavaScriptのオブジェクトリテラルと同じ感覚で書ける
  • プロパティの区切りはセミコロン(;)でもカンマ(,)でもよいが、本記事では公式ハンドブックに合わせてセミコロンを使う
  • 一度型注釈を付けると、型と異なる値を代入したり、定義にないプロパティへアクセスしたりすると型エラーになる

なお、初期値から型を推論できる場合は、型注釈を省略しても同等の型が付きます。型注釈を書くか省略するかの判断基準については、型推論の記事を参照してください。

なかむぅ
なかむぅ
TypeScriptの型推論を理解しておくと、型注釈を「書くべき場所」と「省略してよい場所」の判断がスムーズになります。
【TypeScript】型推論ってなに?型を書かなくても型が決まる仕組みを解説
【TypeScript】型推論ってなに?型を書かなくても型が決まる仕組みを解説TypeScriptの型推論を初心者向けにやさしく解説。型を書かなくても型が決まる仕組みや、省略できる場面・書くべき場面がすっきりわかります。 ...

ネストしたオブジェクトの型注釈

プロパティの値がさらにオブジェクトになっている場合も、同じ要領で型注釈をネストして書けます。

const user: {
  name: string;
  age: number;
  address: {
    city: string;
    zip: string;
  };
} = {
  name: "Alice",
  age: 30,
  address: {
    city: "Tokyo",
    zip: "100-0001",
  },
};

console.log(user.address.city); // "Tokyo"

このコードのポイントは次の通りです。

  • ネストしたオブジェクトの型は、入れ子の構造をそのまま型でも表現する
  • 階層が深くなると型注釈の見通しが悪くなる
  • 同じ形を別の場所でも使うなら、後述するtypeinterfaceで名前を付けて再利用するのが定石

階層が3層以上に深くなったら、それは「名前を付けて切り出すべきサイン」だと考えると整理しやすくなります。

関数の引数・戻り値に使う

関数の引数や戻り値の型としても、オブジェクト型注釈はそのまま使えます。複数の値をまとめて受け渡したいときに便利です。

function formatUser(user: { name: string; age: number }): string {
  return `${user.name}(${user.age}歳)`;
}

const message = formatUser({ name: "Alice", age: 30 });
console.log(message); // "Alice(30歳)"

このコードのポイントは次の通りです。

  • 引数の位置に直接{ name: string; age: number }のように書ける
  • 戻り値の型は引数リストの後に: stringのように指定する
  • 同じ形のオブジェクトを複数箇所で受け渡す場合は、後述のtypeinterfaceに切り出すと冗長さが減る

余剰プロパティチェックに注意

オブジェクト型を書いていて初学者がよくつまずくのが、「リテラルで余分なプロパティを書くとエラーになるのに、変数経由なら通る」という挙動です。これは余剰プロパティチェックと呼ばれるTypeScript特有の仕組みです。

type User = { name: string; age: number };

// パターン1:オブジェクトリテラルを直接代入 → エラーになる
const user1: User = {
  name: "Alice",
  age: 30,
  email: "alice@example.com", // エラー:'email' は型 'User' に存在しません
};

// パターン2:一度変数に入れてから代入 → 通ってしまう
const data = {
  name: "Alice",
  age: 30,
  email: "alice@example.com",
};
const user2: User = data; // OK

このコードのポイントは次の通りです。

  • オブジェクトリテラルを直接代入したときだけ、定義にないプロパティが余剰プロパティチェックで検出される
  • 一度変数に入れてから代入すると、構造的に互換性があるとみなされてエラーが出ない
  • タイポ(emialなど)を防ぎたい場合はリテラル直書きの方が安全

「変数経由だと通る」のはバグというより設計上の挙動です。型を厳しく保ちたい場面ではリテラル直書きを意識し、緩く渡したい場面では変数経由を使う、という使い分けが現場では一般的です。

type・interfaceで名前を付けたオブジェクト型を定義する

同じ形のオブジェクトを複数箇所で使うなら、毎回型注釈を書くのではなく、名前を付けて再利用するのが定石です。TypeScriptには名前を付ける手段がtypeinterfaceの2つあります。

typeで型エイリアスを作る

typeを使うと、任意の型に名前を付けられます。オブジェクト型に名前を付ける用途でもよく使われます。

type User = {
  name: string;
  age: number;
};

const user: User = { name: "Alice", age: 30 };

function formatUser(user: User): string {
  return `${user.name}(${user.age}歳)`;
}

このコードのポイントは次の通りです。

  • type 名前 = 型の形で、任意の型に別名を付けられる
  • オブジェクト型だけでなく、ユニオン型・リテラル型など幅広い型に名前を付けられる汎用的な仕組み
  • 一度定義すれば、以降はUserという短い名前で参照できる

typeそのものの詳しい使い方は別記事で解説しています。

なかむぅ
なかむぅ
type(型エイリアス)はTypeScriptの中でも頻繁に使う機能なので、こちらの記事で深掘りしておくとコードの幅が広がります。
TypeScriptのtypeエイリアスとは?基本の書き方と使いどころを整理するTypeScriptのtype(型エイリアス)の基本を解説。オブジェクトやユニオン型の書き方、interfaceとの違いを整理しました。型の再利用でコードの可読性を高めるメリットと使いどころがわかります。...

interfaceで型を定義する

interfaceを使っても、オブジェクト型に名前を付けて再利用できます。

interface User {
  name: string;
  age: number;
}

const user: User = { name: "Alice", age: 30 };

function formatUser(user: User): string {
  return `${user.name}(${user.age}歳)`;
}

このコードのポイントは次の通りです。

  • interface 名前 { ... }の形で、オブジェクト型に名前を付けられる
  • typeと違って末尾の=は不要、ブロックの中にプロパティと型を書く
  • 機能的にはtypeと多くの面で重なるが、継承や宣言マージといったinterface独自の機能もある

typeinterface、どちらを使うべきか?」は迷いどころですが、詳しい使い分けは別記事で解説しています。

なかむぅ
なかむぅ
interfaceの使い方を体系的に学びたい方はこちら。継承や拡張など、interface特有の機能まで丁寧に解説しています。
TypeScriptのinterfaceとは?オブジェクト型定義の基本と使い方TypeScriptのinterfaceの基本から使い方、typeとの違いまで初心者向けにわかりやすく解説します...
なかむぅ
なかむぅ
typeとinterfaceの使い分けで迷ったら、両者を比較した記事もあわせて読んでみてください。
TypeScriptのinterfaceとtypeの違いって?3つの違いと使い分け方TypeScriptのinterfaceとtypeの違いを3つのポイントで整理。ユニオン型や拡張の書き方など、使い分けの判断基準がすっきりわかります。...

インデックスシグネチャでキーが動的なオブジェクト型を表す

ここまでは「プロパティ名が事前に決まっているオブジェクト」の型を扱ってきました。一方、辞書(連想配列)のようにプロパティ名が動的に増減するオブジェクトを型で表したいケースもあります。そのときに使うのがインデックスシグネチャです。

基本の書き方|[key: string]: 型

インデックスシグネチャは{ [key: string]: 値の型 }の形で書きます。「文字列キーに対し、値の型は◯◯」という意味です。

たとえば、商品名をキー、在庫数を値とする辞書的なオブジェクトの型は次のように書きます。

const inventory: { [key: string]: number } = {};

inventory["apple"] = 10;
inventory["banana"] = 5;
inventory["cherry"] = 20;

console.log(inventory["apple"]); // 10

このコードのポイントは次の通りです。

  • [key: string]のうち、keyの名前はわかりやすければ何でもよい(productNameなどでもOK)
  • キーは文字列なら何でも許容され、値はすべてnumber型として扱われる
  • 通常のプロパティ名と組み合わせて、{ id: string; [key: string]: number }のような書き方もできる(ただし固定プロパティの型もインデックスシグネチャの値型に互換である必要がある)

数値キーを使いたい場合は、[index: number]: 型の形で書けます。これは配列ライクなオブジェクトを表現したいときに使われます。

const scores: { [index: number]: string } = {};
scores[0] = "Alice";
scores[1] = "Bob";

インデックスシグネチャの注意点

インデックスシグネチャは便利ですが、型安全性が緩くなるという大きな注意点があります。存在しないキーへのアクセスもコンパイルエラーにならないため、実行時にundefinedが返ってきて思わぬバグにつながることがあります。

const inventory: { [key: string]: number } = {
  apple: 10,
};

const value = inventory["banana"]; // 型上は number 扱いだが、実際は undefined が返る
console.log(value + 1); // 型エラーにならず、実行時に NaN になってしまう

このコードのポイントは次の通りです。

  • 存在しないキーへのアクセスも型上は値の型として扱われ、コンパイル時に検出されない
  • 実行時にはundefinedが返るため、計算や文字列操作でバグになりやすい
  • tsconfig.jsonnoUncheckedIndexedAccessオプションを有効にすると、取り出した値の型がnumber | undefinedのようになり、上のコードのvalue + 1の部分でコンパイルエラーになる(先に存在チェックが必要になる)

noUncheckedIndexedAccessstrictオプションに含まれていない比較的新しめの設定です。これを有効にすると、インデックスシグネチャや配列の添字アクセスで取得した値が必ずundefinedの可能性を含むようになり、利用前に存在チェックが必要になります。先ほどのコード例で言えば、value + 1のように直接計算しようとした時点で型エラーになるため、undefinedチェック漏れによるバグを未然に防げます。型安全性を高めたいプロジェクトでは積極的に有効化するのがおすすめです。

Record型・Mapとの使い分け

「キーが動的なオブジェクトの型」を表す手段は、インデックスシグネチャ以外にもRecord<K, V>型とMap<K, V>があります。3つの違いを表で整理します。

観点 インデックスシグネチャ Record<K, V> Map<K, V>
適したキーの状態 完全に動的(無限の文字列) 既知のキー集合(リテラル型のユニオンなど) 動的・既知どちらも可
型安全性 緩い(存在しないキーも通る) キーが既知なら強い 強い
キーに使える型 stringnumbersymbol 任意の型 任意の型(オブジェクトもキーに使える)
実行時の正体 プレーンなオブジェクト プレーンなオブジェクト Mapオブジェクト

まずはこう覚えればOKです。「キーが完全に未知ならインデックスシグネチャ、キー候補が決まっているならRecord型、キーにオブジェクトを使いたい・順序保持したいならMap

オブジェクト型でよくある落とし穴と書き方のコツ

最後に、オブジェクト型まわりで初学者がぶつかりやすい代表的な落とし穴を3つ紹介します。事前に知っておくだけで、エラーに遭遇しても落ち着いて対処できるようになります。

落とし穴1|object型ではプロパティアクセスができない

最初の章でも触れましたが、object型単体に代入したオブジェクトは、プロパティ構造が保証されないためアクセスできません。

// NG:object 型ではプロパティアクセスができない
function printUserBad(user: object) {
  console.log(user.name); // エラー:プロパティ 'name' は型 'object' に存在しません
}

// OK:プロパティを持つオブジェクト型を定義する
function printUserGood(user: { name: string }) {
  console.log(user.name); // OK
}

printUserGood({ name: "Alice" });

このコードのポイントは次の通りです。

  • object型は「何かしらのオブジェクト」しか保証しないため、プロパティアクセスは型エラーになる
  • 受け取りたい形が決まっているなら、その形を書いたオブジェクト型を引数に指定する
  • 「とりあえず受け取りたいからobject」は、ほぼ常に悪手と覚えておくと安心

落とし穴2|配列もobject型に代入できてしまう

JavaScriptでは配列もオブジェクトの一種なので、object型には配列も代入できてしまいます。

const value: object = [1, 2, 3]; // OK:配列もオブジェクト

console.log(typeof value); // "object"
console.log(Array.isArray(value)); // true

このコードのポイントは次の通りです。

  • typeof演算子は配列に対しても"object"を返すため、JavaScriptレベルで「オブジェクトか配列か」を区別するにはArray.isArrayを使う
  • TypeScriptでも、object型に入れた値が「配列ではないオブジェクト」だと型レベルで保証することはできない
  • 配列を受け付けたくない場合は、プロパティを定義したオブジェクト型を使うか、型ガードで絞り込む

落とし穴3|余剰プロパティチェックは「リテラル直書き」のときだけ

すでにH3-3-4でも触れたとおり、余剰プロパティチェックはオブジェクトリテラルを直接代入したときにしか働きません。「タイポを防ぎたい」「型をきっちり守りたい」場面では、変数経由ではなくリテラルを直接渡すことを意識すると、TypeScriptの恩恵を最大限に受けられます。

よくある質問

object型とObject型は何が違いますか?

object(小文字)はプリミティブ以外のあらゆる値を表す型で、TypeScript独自の型です。一方Object(大文字始まり)はJavaScriptに組み込まれているグローバルなObject型を指し、nullundefined以外のほぼ何でも代入できる広すぎる型です。2つを比べるとまだobjectの方が見かける場面がありますが、それでも単体で使うことは少なく、プロパティを書いたオブジェクト型を使うのが基本です。Objectを型注釈に使うことは実務ではまず推奨されません。

プロパティ付きのオブジェクト型はtypeinterfaceどちらで書くべきですか?

どちらでも書けます。TypeScript公式ハンドブックでは「目安としては、typeにしかない機能が必要になるまではinterfaceを使う」という方針が示されています。一方、現場では「typeを基本として、宣言マージや継承などinterfaceの機能が必要なときだけinterfaceを使う」という方針を採るチームもあり、どちらが絶対的に正解というわけではありません。プロジェクトのスタイルガイドがあればそれに従い、なければ公式の方針に倣ってinterfaceから始めるのが無難です。詳しい使い分けは別記事で扱っているので、そちらを参考にしてください。

{}型は空オブジェクトしか入らない型ですか?

いいえ、これはとても誤解されやすい点です。{}型は「プロパティの要件がない型」と解釈されるため、文字列や数値も含めてnullundefined以外なら何でも代入できてしまいます。空のオブジェクトに限定したい場合は、{}ではなく明確にプロパティを書いた型注釈を使うか、用途によってはRecord<string, never>のような書き方を検討します。実務でターゲットの型として{}を使うのは推奨されません。

キーが動的に増えるオブジェクトの型はどう書きますか?

主な選択肢は2つあります。ひとつは{ [key: string]: 値の型 }というインデックスシグネチャ、もうひとつはRecord<K, V>型です。シンプルにすぐ書きたい場合や、キーが完全に未知の場合はインデックスシグネチャ、キー候補がリテラル型のユニオンとして決まっている場合はRecord型を選ぶと型安全性が高まります。noUncheckedIndexedAccessオプションを有効にすると、インデックスシグネチャ経由のアクセスでも未定義の可能性が型に現れるようになります。

余剰プロパティチェックはどんなときに発動しますか?

オブジェクトリテラルを変数や引数に直接代入したときだけ発動します。一度別の変数に入れてから代入すると、構造的に互換性があるとみなされてエラーが出ません。タイポを早期に検出したい場面では、リテラル直書きの方が安全です。意図的に余分なプロパティを許容したい場合は、変数経由で渡す書き方が役立ちます。

object型にすればどんなオブジェクトでも受け取れますか?

「代入を受け付ける」という意味では受け取れますが、プロパティ構造が保証されないため、受け取った後にobj.nameのようなアクセスができません。実用性が低いので、受け取りたい形が決まっているならその形のオブジェクト型を書く方が、得られる型情報も多く実務的です。汎用的に何でも受け取りたい場合でも、objectよりunknownの方が安全な選択肢になることが多いです。

TypeScriptのobject型と、JavaScriptの「オブジェクト」は同じものですか?

基本的にはほぼ重なりますが、細かい違いがあります。たとえばJavaScriptでtypeof null"object"を返しますが、TypeScriptのobject型にnullを代入することはできません(strictNullChecksが有効な場合)。また、typeof"function"を返す関数も、TypeScriptのobject型には代入できます。「JavaScriptの実行時の挙動」と「TypeScriptの型の世界」は完全には一致しないと覚えておくと混乱しにくくなります。

【付録】さらに学びを深めるためのリソース


さらにTypescriptの学習を進めたい方のために、いくつかのリソースを紹介します。
これらのリソースを活用することで、TypeScriptの型システムについてより深い知識を得ることができるでしょう。

おすすめの書籍

ゼロからわかる TypeScript入門


技術評論社から出版されている「ゼロからわかる TypeScript入門」は、プログラミング初心者や本職プログラマーではない方を主な対象にした入門書です。

変数・条件分岐・ループといった基本から、クラスやインターフェース、モジュールまで段階的に学べる構成になっています。最終章ではWeb APIとJSONを使った非同期Webアプリの作成も体験できるので、「実際に動くものを作る」ところまで到達できます。

プロを目指す人のためのTypeScript入門


技術評論社の「プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで」、通称 ブルーベリー本 です。
JavaScriptの仕様とTypeScript独自の機能を両方押さえつつ、リテラル型・ユニオン型・keyof型・ジェネリクスなど、高度な型表現まで踏み込んで解説しています。TypeScriptの型システムの表現力を本格的に学べる一冊です。

オンラインで参照できる公式ドキュメント

TypeScript公式ハンドブック


https://www.typescriptlang.org/docs/
TypeScriptの公式ドキュメントです。
intersection型を含む、すべての型システムの機能について詳細な説明があります。

TypeScript Deep Dive


https://basarat.gitbook.io/typescript/
TypeScriptの深い部分まで掘り下げて解説しているオンラインブックです。
無料で読むことができ、intersection型についても詳しく説明されています。

TypeScriptの学習は終わりがありません。
新しい機能が常に追加され、より良い書き方が発見されています。
継続的に学習を続けることで、より良いTypeScriptプログラマーになれるはずです。


まとめ

TypeScriptのオブジェクト型は名前が似た型がいくつもあって最初は迷いやすいですが、ポイントを押さえれば実務で困らないレベルに到達できます。最後にこの記事のポイントを振り返ります。

  • TypeScriptで「オブジェクトの型」が指すものは、object(小文字)/プロパティ付きの独自型/Object(大文字)の3つに分かれる
  • object型・Object型・{}型はいずれも実務でほぼ使わず、プロパティを書いたオブジェクト型を使うのが基本
  • プロパティ付きオブジェクト型は{ name: string; age: number }のように書き、再利用するならtypeinterfaceで名前を付ける
  • インデックスシグネチャは動的キーに便利だが型安全性が緩いので、用途によってはRecord型やMapを選ぶ
  • 余剰プロパティチェックやobject型でのプロパティアクセス不可など、初学者がつまずきやすい挙動は事前に理解しておくと安全

ここまで読み進められたら、TypeScriptのオブジェクト型の地図はもう頭の中に入っているはずです。あとは実際にコードを書いてみて、迷ったときに本記事や関連記事に立ち戻ってもらえれば、自分のものとして身についていきます。

なかむぅ
なかむぅ
オブジェクト型を再利用する手段としてのtypeinterfaceの使い分けが気になる方は、こちらの比較記事へ進んでみましょう。
TypeScriptのinterfaceとtypeの違いって?3つの違いと使い分け方TypeScriptのinterfaceとtypeの違いを3つのポイントで整理。ユニオン型や拡張の書き方など、使い分けの判断基準がすっきりわかります。...

※本記事の本文案はAIを活用して作成していますが、記載している内容およびコードは筆者が実際に調査、検証・実行し、内容の正確性を確認した上で公開しています。