🛋️
TypeScriptのReadonly<T>を知ろう
概要
別記事を書くにあたりReadonly<T>を理解しようの会
Readonly<T>とは
ユーティリティ型の1つ。
型Tのプロパティにreadonlyを付けた状態で返す時に使う。
参考: https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype
type Hoge = string[];
type Fuga = [string, number, boolean];
type Piyo = { name: string };
const hoge: Readonly<Hoge> = ["ほげ", "ふが"]; // readonly string[]
const fuga: Readonly<Fuga> = ["ほげ", 20, true]; // readonly [string, number, boolean]
const piyo: Readonly<Piyo> = { name: "ほげ" }; // { readonly name: string }
hoge.push("ぴよ"); // 🚫readonly string[] なのでNG
fuga.push("ぴよ"); // 🚫readonly [string, number, boolean] なのでNG
piyo.name = "ぴよ"; // 🚫{ readonly name: string }なのでNG
readonlyを付与できない型を対応しようとしてもエラーにはならないがreadonly特有の動きとかは特にない。
type Hoge = string;
const hoge: Readonly<Hoge> = "ほげ"; // ✅エラーにはならないが型はstringになる
ちなみに
ネストされたオブジェクトにはreadonlyが付かない。
type Hoge = {
name: "ほげ";
birthday: { year: number; month: number; day: number };
};
const hoge: Readonly<Hoge> = {
name: "ほげ",
birthday: { year: 2000, month: 1, day: 1 },
}; // { readonly name: "ほげ"; readonly birthday: { year: 2000; month: 1; day: 1} }
hoge.name = "ふが"; // 🚫nameはreadonlyなのでNG
hoge.birthday.year = 2001; // ✅birthday.yearはreadonlyじゃないのでOK
なのでプロパティ全てをreadonlyにしたい場合は Readonly<T> は使わず、
以下のように as const をして型定義してあげるとOK。
const object = {
name: "ほげ",
birthday: { year: 2000, month: 1, day: 1 },
} as const;
type Hoge = typeof object; // { readonly name: "ほげ"; readonly birthday: { readonly year: 2000; readonly month: 1; readonly day: 1} }
const hoge: Hoge = {
name: "ほげ",
birthday: { year: 2000, month: 1, day: 1 },
};
hoge.name = "ふが"; // 🚫nameはreadonlyなのでNG
hoge.birthday.year = 2001; // 🚫birthday.yearはreadonlyなのでNG
Discussion