結論
Array
は不変なのに対し $ReadOnlyArray
は共変なのでポリモーフィックな型を扱えて便利やで。
例
ユーザ情報を表す UserT
型とより詳細なユーザ情報を有する UserWithDetailsT
型があるとする。
それぞれの型の関係性は UserT
≤ UserWithDetails
となっている。
type UserT = { name: string }
type UserDetailsT = { name: string, age: number }
このとき UserT
と UserDetailsT
が混在しうる Array
を共通処理しようとして、以下のようにするとエラーとなる。
const userList: Array<UserT> = [{ name: 'alice' }]
const userDetailsList: Array<UserDetailsT> = [{ name: 'bob', age: 20 }]
// Error
const userOrUserDetailsList: Array<UserT|UserDetailsT> = true ? userList : userDetailsList
なぜなら Array
は不変(invariant)で Array<UserT>
と Array<UserDetailsT>
に互換性がないため。それに対して $ReadOnlyArray
は共変(covariant)なので互換性を持てる([doc](ref: https://flow.org/en/docs/types/arrays/#toc-readonlyarray))。
// OK
const readOnlyUserOrUserDetailsList: $ReadOnlyArray<UserT|UserDetailsT> = true ? userList : userDetailsList
意気込み
上記のメリットに加え、 Array.prototype.push
などによる Array
への副作用も基本的に好ましくないので、今後は特に何も考えずに $ReadOnlyArray
を使っていく所存。