TypeScript なんもわからん…
Readonly と as const がよく判らなかったから調べたメモ
Readonly
TypeScriptの型システムでは、インターフェース上の個々のプロパティをreadonlyとしてマークすることができます。これにより、関数的に作業することができます(予期しない変更は良くありません)。
cf. Readonly - TypeScript Deep Dive 日本語版
オブジェクトのプロパティを変更不可にするイメージ?
type Idol = Readonly<{ name: string; type: 'cute' | 'cool' | 'pop' | 'sexy'; school?: string; brand?: string; songs: { [key: string]: string[]; }; }>; const Hoshimiya: Idol = { name: '星宮いちご', type: 'cute', school: 'スターライト学園', brand: 'Angely Sugar', songs: { cute: ['アイドル活動!'], cool: ['Signalize!'] }, }; Hoshimiya.type = 'cool'; // => Cannot assign to 'type' because it is a read-only property. Hoshimiya.songs.cute.push('輝きのエチュード'); // 変更できる
readonly な型が与えられてるオブジェクト直下のプロパティは変更しようとするとエラーになるけど、Objectや配列の中身は変更できるっぽい。
as const ( const assertion )
const Hoshimiya = { name: '星宮いちご', type: 'cute', school: 'スターライト学園', brand: 'Angely Sugar', songs: { cute: ['アイドル活動!'], cool: ['Signalize!'] }, } as const; Hoshimiya.type = 'cool'; // => Cannot assign to 'type' because it is a read-only property. Hoshimiya.songs.cute.push('輝きのエチュード'); // => Property 'push' does not exist on type 'readonly ["アイドル活動!"]'. // スプレッド演算子で展開して別オブジェクトするのはOK {...Hoshimiya, name: '霧矢あおい', type: 'cool'}; //=> {name: '霧矢あおい', type: 'cool', ...};
as const
だと、ネストしているオブジェクト内にも readonly が与えられて変更を加えようとしてもエラーになるっぽい。
(この構造だと引退したアイドルにしか使えなさそう…)
学校も曲も変更できないとか引退したアイドル図鑑作るとかでしか使えなさそうな型なので、こんな感じ?
type Idol = { readonly name: string; type: 'cute' | 'cool' | 'pop' | 'sexy'; school?: string; brand?: string; songs?: { [key: string]: string[]; }; }
Readonly でも as const でも別のオブジェクトに代入して変更することができてしまう
type IdolBase = Readonly<{ name: string; }>; const Hoshimiya: IdolBase = { name: '星宮いちご', }; const Shibuki = Hoshimiya; // 代入はエラーにならない Shibuki.name = '紫吹蘭'; // => Cannot assign to 'name' because it is a read-only property. const Kiriya: { name: string } = Hoshimiya; Kiriya.name = '霧矢あおい'; // 別途型を指定していると変更できてしまう console.log(Hoshimiya); // => { "name": "霧矢あおい" } const Otome: any = Hoshimiya; // any 型に代入すると何でも変更できる Otome.name = '有栖川おとめ'; Otome.unit = 'ぽわプリ〜' console.log(Hoshimiya); // => { "name": "有栖川おとめ", "unit": "ぽわプリ〜" } console.log(Hoshimiya === Kiriya) // true
Object.freeze
を使うと実行時にエラーにすることができる
const Hoshimiya: IdolBase = Object.freeze({ name: '星宮いちご', }); const Kiriya: { name: string } = Hoshimiya; Kiriya.name = '霧矢あおい'; // => TypeError: Cannot assign to read only property 'name' of object '#<Object>'
感想
ざっくり Readonly も as const もオブジェクトの変更をエラーで教えてくれるようにするもので、as const はネストしている配列やオブジェクトにも再帰的に readonly
を指定してくれる。
ただし、オブジェクトを型が異なる別のオブジェクトに代入してしまうと、参照元のオブジェクトのプロパティを変更できてしまうので注意が必要。
関数型的な考え方をしていればオブジェクトをそのまま他のオブジェクトに代入する事自体がキモチワルイ感じだけど、防げないのでガチガチに固めるなら Object.freeze
を使うのが良さそう。
[参考]
- Readonly - TypeScript Deep Dive 日本語版
- TypeScript3.4 の const assertion - Qiita
- Typescript 3.4のconstアサーションを試す - Qiita
- Typescriptのconst assertionは必ずしも書き換え不可能ではない - Qiita

プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発
- 作者:Boris Cherny
- 発売日: 2020/03/16
- メディア: 単行本(ソフトカバー)

- アーティスト:STAR☆ANIS,わか from STAR☆ANIS,わか・ふうり・ゆな・れみ・えり・るか from STAR☆ANIS,わか・りすこ・るか from STAR☆ANIS
- 発売日: 2014/12/13
- メディア: CD
毎週火曜日アイカツ!をみましょう!!!8/18(火)から毎週火曜日にBNP公式YouTubeチャンネルでアイカツ!シリーズの配信がスタート♪
— アイカツプラネット!&アイカツオンパレード!アニメ公式 (@aikatsu_anime) 2020年8月6日
20時から『アイカツ!』、20時30分から『アイカツフレンズ!』をプレミア公開&2週間アーカイブ配信☆
アツい配信活動!はじまります!https://t.co/6w2fuEmbj7#aikatsu #aikatsufriends pic.twitter.com/gAjV1Bl48A