Search code examples
typescripteslinttypescript-eslint

What's the difference between ReadonlyArray and "readonly arr: T[]"?


See this playground.

interface Feature {
  readonly name: string;
}

// <Test>
// This is OK
interface Foo1 {
  readonly arr: ReadonlyArray<Feature>;
}
function save1(foo: Foo1) {
  console.log(foo);
}
// </Test>


// <Test>
// bad? why?
interface Foo2 {
  arr: ReadonlyArray<Feature>;
}
function save2(foo: Foo2) {
  console.log(foo);
}
// </Test>

// <Test>
// bad? why?
interface Foo3 {
  readonly arr: Feature[];
}
function save3(foo: Foo3) {
  console.log(foo);
}
// </Test>

I thought Foo1, Foo2, and Foo3 are equivalent, but @typescript-eslint/prefer-readonly-parameter-types says otherwise. In summary,

  • Foo1 has both readonly and ReadonlyArray
  • Foo2 only has ReadonlyArray
  • Foo3 only has readonly

How are these interfaces different?


Solution

  • In function save2, I'm allowed to do

    foo.arr = [];
    

    And in save3, I'm allowed to do

    foo.arr.push({name: 'bar'});
    

    None of these operations are allowed in save1.