みんなのちからになりたい

コピペでブログラムつくっていきたい

GPT3.5くんと学ぶはじめてのTypeScript:constとreadonly

USER

typescriptのconstとreadonlyの違いを教えてください どちらも代入できないと理解しているのですが。。。

ASSISTANT

TypeScriptにおけるconstreadonlyは、両方とも変数やプロパティの再代入を防ぐための方法ですが、使用される文脈や適用される場所が異なります。

  1. const:
    • constは、変数宣言時に使用されます。constで宣言された変数は再代入できません。ただし、オブジェクトや配列などの参照型については、その参照自体は不変ですが、参照先のプロパティや要素は変更できます。
    • constブロックスコープを持ちます。つまり、ブロック内でのみ有効です。
const x = 10;
x = 20; // エラー: 再代入不可

const obj = { name: "Alice" };
obj.name = "Bob"; // 可能
obj = { name: "Charlie" }; // エラー: 再代入不可
  1. 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

どういたしまして!もしご質問がありましたら、いつでもお知らせください。お力になれることがあれば喜んでお手伝いいたします。


www.typescriptlang.org


constアサーション「as const」 (const assertion)

typescriptbook.jp

オブジェクトリテラルの末尾にas constを記述すればプロパティがreadonlyでリテラルタイプで指定した物と同等の扱いになります。

const pikachu = {
  name: "pikachu",
  no: 25,
  genre: "mouse pokémon",
  height: 0.4,
  weight: 6.0,
} as const;

代入はもちろんできません。