USER
typescriptのconstとreadonlyの違いを教えてください どちらも代入できないと理解しているのですが。。。
ASSISTANT
TypeScriptにおけるconst
とreadonly
は、両方とも変数やプロパティの再代入を防ぐための方法ですが、使用される文脈や適用される場所が異なります。
const
:const
は、変数宣言時に使用されます。const
で宣言された変数は再代入できません。ただし、オブジェクトや配列などの参照型については、その参照自体は不変ですが、参照先のプロパティや要素は変更できます。const
はブロックスコープを持ちます。つまり、ブロック内でのみ有効です。
const x = 10; x = 20; // エラー: 再代入不可 const obj = { name: "Alice" }; obj.name = "Bob"; // 可能 obj = { name: "Charlie" }; // エラー: 再代入不可
readonly
:readonly
は、インターフェースのプロパティまたはクラスのプロパティの宣言時に使用されます。これにより、そのプロパティは読み取り専用になります。readonly
は、再代入を防ぐだけでなく、そのプロパティが宣言された時点から変更できなくなります。
interface Person { readonly name: string; } let person: Person = { name: "Alice" }; person.name = "Bob"; // エラー: 読み取り専用のため変更不可
要するに、const
は変数の再代入を防ぐのに対して、readonly
はプロパティの再代入を防ぎます。また、const
は変数宣言で使用され、readonly
はプロパティ宣言で使用されます。
USER
説明はわかりました では以下はどういうことでしょう?
const numbers: readonly number[] = [1, 2, 3];
ASSISTANT
このコードは、numbers
という配列を定義し、その配列の要素が読み取り専用であることを示しています。
const numbers: readonly number[] = [1, 2, 3];
これは、numbers
という配列があり、その要素の型がnumber
であることを示しています。また、readonly
キーワードが配列の前に置かれており、これにより配列の要素が読み取り専用になります。
このように宣言された配列は、要素を追加、削除、または変更することができません。これは、配列自体はconst
キーワードで宣言されているため、再代入ができないこととは異なります。readonly
は配列の要素が変更不可であることを示しています。
例えば、以下のようなコードはエラーとなります。
numbers.push(4); // エラー: 読み取り専用のため変更不可
このように、readonly
を使うことで、不用意な要素の変更や削除を防ぐことができます。
USER
ということは、constだけだとnumbers変数自体に再代入はできないが、要素自体には変更できるということですか?
ASSISTANT
はい、その通りです。
const numbers: number[] = [1, 2, 3];
この場合、numbers
配列自体はconst
で宣言されているので、再代入はできません。しかし、配列の要素である数値は変更できます。
numbers.push(4); // 可能 numbers[0] = 5; // 可能
このように、const
キーワードは変数の再代入を防ぎますが、配列やオブジェクトなどの参照型の場合、その中身の要素やプロパティの変更を防ぐことはありません。
一方で、readonly
を使った場合は、配列やオブジェクトの要素やプロパティ自体を変更できなくなります。
USER
ありがとう!よくわかりました
ASSISTANT
どういたしまして!もしご質問がありましたら、いつでもお知らせください。お力になれることがあれば喜んでお手伝いいたします。
constアサーション「as const」 (const assertion)
オブジェクトリテラルの末尾にas constを記述すればプロパティがreadonlyでリテラルタイプで指定した物と同等の扱いになります。
const pikachu = { name: "pikachu", no: 25, genre: "mouse pokémon", height: 0.4, weight: 6.0, } as const;
代入はもちろんできません。