readonly
書き換えてはいけない項目がある
Work の id は、その作品を見分けるための番号です。タイトルは後から直してよくても、id が変わると別の作品になってしまいます。
けれど型の上では、title も id も同じ扱いです。
interface Work {
id: number;
title: string;
published: boolean;
}
const work: Work = { id: 1, title: "プロフィールサイト", published: true };
work.id = 99; // 通ってしまうプロパティ名の前に readonly を付けると、代入だけを止められます。
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 が禁止するのは、できあがった後の代入だけです。オブジェクトを組み立てるときは今までどおり値を書けます。
const copy: Work = { id: work.id, title: "自己紹介カード", published: false };だから readonly を付けた型を扱うときの基本は、書き換えるのではなく新しいオブジェクトを作って返す、という形になります。
function renameWork(work: Work, newTitle: string): Work {
return { id: work.id, title: newTitle, published: work.published };
}元のオブジェクトには触っていないので、呼び出した側の手元のデータが知らないうちに変わることもありません。React では、この「作り直して返す」書き方がそのまま state 更新のやり方になります。
効くのは検査のときだけ
readonly は TypeScript の検査のための印です。コンパイル後の JavaScript には残らないので、実行時に代入を止める力はありません。あくまで、書いている最中に間違いを見つけるための道具です。
手を動かす
演習では id を readonly にして、タイトルだけを差し替えた新しい作品を返す関数を書きます。
要件
Workのidをreadonlyにする- 引数のオブジェクトを書き換えない
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":"スキル表"}ヒント
編集 LuaGate編集部