「オブジェクトの再代入」とは何を指しているのか
まず言葉の整理からいきます。
ここでいう「オブジェクトの再代入」は、変数に入っているオブジェクトそのものを、別のオブジェクトに入れ替えることを指します。
type User = {
name: string;
age: number;
};
let user: User = {
name: "Taro",
age: 20,
};
user = {
name: "Hanako",
age: 18,
}; // ← これが「再代入」
TypeScript一方で、
user.name = "Jiro"; // これは「プロパティの書き換え」
TypeScriptこれは「再代入」ではなく、「同じオブジェクトの中身を変えている」だけです。
この2つを頭の中でちゃんと分けておくと、let / const / readonly の意味が一気にクリアになります。
let と const と「オブジェクトの再代入」
let の場合:オブジェクトの再代入も中身の変更もOK
type User = {
name: string;
age: number;
};
let user: User = {
name: "Taro",
age: 20,
};
user.name = "Jiro"; // OK(プロパティの変更)
user = {
name: "Hanako",
age: 18,
}; // OK(オブジェクトごと入れ替え)
TypeScriptlet で宣言した変数は、「変数に入っている参照そのものを入れ替えてよい」ので、
オブジェクトの再代入も自由にできます。
const の場合:再代入はNGだが、中身の変更はOK
const user: User = {
name: "Taro",
age: 20,
};
user.name = "Jiro"; // OK(中身の変更)
// user = { name: "Hanako", age: 18 }; // エラー:再代入はできない
TypeScriptここが最初に一番混乱しやすいポイントです。
const は「変数に入っている“参照”を変えられない」だけであって、
「オブジェクトの中身が不変になる」という意味ではありません。
user = ...のように、別のオブジェクトを丸ごと代入し直すのは NGuser.name = ...のように、同じオブジェクトのプロパティを書き換えるのは OK
この違いを、意識的に見分けられるようになると、const の挙動がスッと腑に落ちます。
型と再代入:「同じ型のオブジェクト」しか入れ替えられない
型が合わないオブジェクトは再代入できない
type User = {
name: string;
age: number;
};
let user: User = {
name: "Taro",
age: 20,
};
user = {
name: "Hanako",
age: 18,
}; // OK
user = {
name: "Ken",
// age がない
}; // エラー:Property 'age' is missing
TypeScript変数 user の型は User なので、
「再代入するときも、User 型のオブジェクトでなければならない」というルールが常に効いています。
つまり、再代入は「変数の中身を入れ替える」だけでなく、
「型の契約を守っているかどうかを再チェックされるタイミング」でもあります。
readonly と再代入:「変えられない」のはどこか
readonly プロパティは「中身の変更」が禁止される
type User = {
readonly id: number;
name: string;
};
let user: User = {
id: 1,
name: "Taro",
};
user.name = "Jiro"; // OK
// user.id = 2; // エラー:id は readonly
TypeScriptreadonly は「プロパティの書き換え」を禁止しますが、
変数自体の再代入は別の話です。
user = {
id: 2,
name: "Hanako",
}; // これはOK(user 変数に別の User を入れ直しているだけ)
TypeScriptここで起きているのは、
user.id = 2→ 「同じオブジェクトのidを変えようとしている」ので NGuser = { id: 2, ... }→ 「変数userに別のオブジェクトを入れている」ので OK
という違いです。
変数自体を「再代入不可」にしたいなら const
const user: User = {
id: 1,
name: "Taro",
};
// user = { id: 2, name: "Hanako" }; // エラー:const なので再代入不可
TypeScript- 「プロパティを書き換えたくない」→
readonly - 「変数に別のオブジェクトを入れ直したくない」→
const
この2つは、守っている対象が違います。
「どこを固定したいのか?」を意識して、readonly と const を使い分けるのが大事です。
オブジェクトの再代入と「参照の共有」
同じオブジェクトを複数の変数が指している場合
type User = {
name: string;
};
let a: User = { name: "Taro" };
let b = a;
b.name = "Jiro";
console.log(a.name); // "Jiro"
TypeScriptここでは、a と b は同じオブジェクトを参照しています。b.name を変えると、a.name も変わって見えるのはそのためです。
一方で、再代入すると「どの変数がどのオブジェクトを指しているか」が変わります。
let c: User = { name: "Taro" };
let d = c;
d = { name: "Hanako" };
console.log(c.name); // "Taro"
console.log(d.name); // "Hanako"
TypeScriptここでは、
- 最初は
cとdが同じオブジェクトを指していた d = { ... }で、dだけ別のオブジェクトを指すようになった
という状態です。
「プロパティの変更」と「再代入」は、参照の共有の観点でもまったく違う動きになる
この感覚を持っておくと、バグの原因を追いやすくなります。
初心者がまず掴んでおきたい「オブジェクトの再代入」の感覚
押さえておきたいポイントを、あえてシンプルにまとめるとこうです。
- 「再代入」は、変数が指しているオブジェクトそのものを入れ替えること
letは再代入OK、constは再代入NG(でも中身の変更はOK)- 型は「再代入のたびに」チェックされるので、常にその型の契約を守る必要がある
readonlyは「プロパティの書き換え」を禁止するが、「変数への再代入」とは別物- 同じオブジェクトを複数の変数が参照しているとき、「プロパティ変更」と「再代入」で挙動が大きく変わる
「今自分がやっているのは、オブジェクトの“中身”を変えているのか?
それとも、変数が指している“オブジェクトそのもの”を入れ替えているのか?」
この問いを、コードを書くときに一瞬だけでも意識できるようになると、let / const / readonly / 型チェックの意味が、かなりクリアに見えてきます。

