概要
TypeScriptには定数を宣言する仕組みとして、constやas constが存在します。
ただ、オブジェクトや配列をconstで定義したとしても、中の値は自由に書き換えれるなどの注意点があります。
これを例とともに見ていきたいと思います。
動作環境: TS5.4.3
const
constは定数を宣言できますが、配列やオブジェクトで扱うときに注意が必要です。 数値や文字列をconstで定義して、後から置き換えようとするともちろん怒られます。
const num = 0 num = 1 // Cannot assign to 'num' because it is a constant.(2588)
一方でオブジェクトの値の置き換えは通ってしまいます。
const obj = {test: 1} obj.test = 2 // 通る
これは、一度宣言したobj自体をまるっと書き換えているのではなく、objの存在はそのままで中のプロパティのみ書き換えているからです。
配列の場合もconstで宣言しても内部の要素は書き換え可能です。
const arr = [1, 2, 3] arr[0] = 5
なお、オブジェクト自体を書き換えようとすると怒られます
const obj = {test: 1} obj = {} // Cannot assign to 'obj' because it is a constant.(2588)
constの中身をreadonlyにするとどうなるか
内部のプロパティを書き換えられないように、readonlyで試しに書いてみます。 この場合、プロパティを書き換えることはできなくなります。
type place = { readonly value: number readonly name: string } const places: place = { value: 0, name: 'コンビニ', } places.name = 'スーパー' // Cannot assign to 'name' because it is a read-only property.(2540)
一方で、以下のようなreadonlyオブジェクトを持つ配列の場合は、配列操作で実質的に値を置き換えれるので注意が必要です。
type place = { readonly value: number readonly name: string } const places: place[] = [ { value: 0, name: 'コンビニ', }, ] // 配列の要素を削除 places.pop() // 新しい要素を入れる places.push({ value: 1, name: '学校', }); console.log(places); // [LOG]: [{ // "value": 1, // "name": "学校" // }]
as const
as constは配列やオブジェクト全体をreadonlyのリテラルとして扱います。
よって内部プロパティを書き換えることはできません。
const obj = {test: 1} as const obj.test = 2 // Cannot assign to 'test' because it is a read-only property.(2540) const arr = [1, 2, 3] as const arr[0] = 5 // Cannot assign to '0' because it is a read-only property.(2540) arr.pop() // Property 'pop' does not exist on type 'readonly [1, 2, 3]'.(2339)