1. 公開中の作品の名前を変える
  2. 下書きの作品の名前を変える
  3. id が大きくても保たれる
コース一覧
TypeScript型設計:オブジェクト・状態・ジェネリクス
readonly

TypeScript型設計:オブジェクト・状態・ジェネリクス

interface、optional property、readonly、union・リテラル型、型ガード、ジェネリクスを扱う全23レッスンの型設計コースです。Profile・Work・ApplicationStateを題材に、APIや画面で扱うデータと状態を壊れにくい型として設計します。既存JavaScriptプロジェクトの移行は次のコースで扱います。

1
オブジェクト型とinterface
01. interface15分
02. 省略可能なプロパティ15分
03. readonly15分
04. interfaceとtype15分
05. ネストした型15分
06. オブジェクト配列15分
07. つくる - Work型とProfile型20分
08. 第4章クイズ15分
2
union・リテラル型・型ガード
01. union型15分
02. リテラル型15分
03. 状態のunion15分
04. typeofで絞り込む15分
05. inと判別で絞り込む15分
06. 状態で表示を切り替える15分
07. つくる - 状態の型表現20分
08. 第5章クイズ15分
3
ジェネリクス入門
01. なぜジェネリクスか10分
02. ジェネリック関数15分
03. 配列を返す汎用関数15分
04. 制約付きジェネリクス15分
05. 組み込みのジェネリクス15分
06. つくる - 汎用フィルタ関数20分
07. 第6章クイズ15分

readonly

書き換えてはいけない項目がある

Work の id は、その作品を見分けるための番号です。タイトルは後から直してよくても、id が変わると別の作品になってしまいます。

けれど型の上では、title も id も同じ扱いです。

TypeScript

interface Work { id: number; title: string; published: boolean; } const work: Work = { id: 1, title: "プロフィールサイト", published: true }; work.id = 99; // 通ってしまう

プロパティ名の前に readonly を付けると、代入だけを止められます。

TypeScript

interface Work { readonly id: number; title: string; published: boolean; } work.id = 99; // エラー Cannot assign to 'id' because it is a read-only property. work.title = "プロフィールサイト v2"; // これは通る

作るときは普通に書ける

readonly が禁止するのは、できあがった後の代入だけです。オブジェクトを組み立てるときは今までどおり値を書けます。

TypeScript

const copy: Work = { id: work.id, title: "自己紹介カード", published: false };

だから readonly を付けた型を扱うときの基本は、書き換えるのではなく新しいオブジェクトを作って返す、という形になります。

TypeScript

function renameWork(work: Work, newTitle: string): Work { return { id: work.id, title: newTitle, published: work.published }; }

元のオブジェクトには触っていないので、呼び出した側の手元のデータが知らないうちに変わることもありません。React では、この「作り直して返す」書き方がそのまま state 更新のやり方になります。

効くのは検査のときだけ

readonly は TypeScript の検査のための印です。コンパイル後の JavaScript には残らないので、実行時に代入を止める力はありません。あくまで、書いている最中に間違いを見つけるための道具です。

手を動かす

演習では id を readonly にして、タイトルだけを差し替えた新しい作品を返す関数を書きます。

要件

  1. Work の id を readonly にする
  2. 引数のオブジェクトを書き換えない
  3. id と published は元の値のまま、title だけを差し替えた新しいオブジェクトを返す

入出力例

renameWork({"id":1,"published":true,"title":"プロフィールサイト"}, "プロフィールサイト v2") → {"id":1,"published":true,"title":"プロフィールサイト v2"} renameWork({"id":2,"published":false,"title":"自己紹介カード"}, "自己紹介カード 改") → {"id":2,"published":false,"title":"自己紹介カード 改"} renameWork({"id":42,"published":true,"title":"スキル一覧の表"}, "スキル表") → {"id":42,"published":true,"title":"スキル表"}

ヒント

`readonly` はプロパティ名の前に書きます

`readonly` を付けると `work.id` への代入がエラーになります。代入で直そうとしないでください

波カッコで新しいオブジェクトを組み立てて、それを返します。組み立てるときは値を書けます

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/08/06

関連レッスン

  • interfaceとtype

    同じ型をinterfaceとtypeの両方で書き比べ、使い分けの基準を持てるようになります。

  • ネストした型

    Workの中のauthor情報を型にし、入れ子になった形を定義できるようになります。

  • オブジェクト配列

    作品一覧にWorkの配列として型を通し、オブジェクト配列を安全に扱えるようになります。

  • つくる - Work型とProfile型

    トラック共通のWork型とProfile型を完成させ、React実践へ持ち込める資産にします。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • プロパティメソッドを属性のようにアクセスできるようにするデコレータ。
  • オブジェクトキーと値のペアで構造を作るデータ
  • TypeScript静的型を加えた JavaScript の上位互換
  • コンパイルソースをバイトコードへ変換する処理
  • JavaScriptWeb で動的な振る舞いを担う言語
  • 関数処理に名前を付けて再利用できる単位
  • 引数位置引数=順番で渡す。
main.ts
学習モード
エディタを読み込んでいます

メモ

readonly

⌘S で保存