TypeScript Readonly<T>ユーティリティ型の解説
Readonly<T>が型レベルですべてのプロパティをイミュータブルにする方法を学びます。フリーズされたオブジェクト、Reduxの状態、イミュータブルデータパターンの例を含みます。
Object Types
詳細な説明
Readonlyの理解
Readonly<T>はTのすべてのプロパティをreadonlyに設定した型を構築します。結果の型のプロパティは初期化後に再代入できません。
構文
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
基本的な例
interface Point {
x: number;
y: number;
}
type ReadonlyPoint = Readonly<Point>;
// 以下と同等:
// {
// readonly x: number;
// readonly y: number;
// }
const p: ReadonlyPoint = { x: 10, y: 20 };
// p.x = 5; // エラー: 読み取り専用プロパティ'x'に代入できません
Object.freeze()との関係
Readonly<T>はObject.freeze()の型レベルの等価物です:
function freeze<T extends object>(obj: T): Readonly<T> {
return Object.freeze(obj);
}
const config = freeze({ host: "localhost", port: 3000 });
// config.port = 8080; // エラー!
シャローReadonlyとディープReadonly
Partialと同様に、Readonlyはシャロー(浅い)です。ネストされたオブジェクトは依然として変更可能です:
interface State {
user: { name: string; age: number };
items: string[];
}
type ReadonlyState = Readonly<State>;
const state: ReadonlyState = { user: { name: "A", age: 1 }, items: [] };
// state.user = { name: "B", age: 2 }; // エラー
state.user.name = "B"; // OK!(ネストされた変更)
深いイミュータビリティにはカスタムのDeepReadonly型またはas constが必要です。
ユースケース
Readonly<T>はReduxの状態型、フリーズされた設定オブジェクト、イミュータブルデータパターン、変更されるべきでないイベントペイロード、変更されるべきでない関数パラメータに使用します。