Ramesh Rajendran
Ramesh Rajendran

Reputation: 38683

Difference between Readonly<[]> and ReadOnlyArray<>

Code 1:

let readonlyArray: ReadonlyArray<string | number> = ["test", 1, 1];

Code 2:

let readonlyArray: Readonly<[string, number]> = ["test", 1, 1];

Both lines of code seem to do similar things. I don't know what is the difference between declaring array as ReadOnly and ReadOnlyArray.

Also, which one is best for performance and why?

Upvotes: 19

Views: 10538

Answers (2)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250056

From a performance point of view, there should not be any difference between the two, as types are erased at runtime and the same javascript will run regardless

There is a fundamental difference between the two types at compile time:

Readonly<T> - Is a type that has the same shape as T but all the properties are read-only. In your case the T is the tuple type [string, number], so it will have all the properties of array as well as the indexes 0 and 1. So we can call the push method, but we can't reassign the concat method.

let readonlyArray: Readonly<[string, number]> = ["test", 1, 1];
readonlyArray.concat = ()=> {} // Not valid, concat is readonly 
readonlyArray.push(1); // This is valid 
readonlyArray[1] =  ""; // Invalid we cannot change a property by indexing 
readonlyArray[3] =  ""; // Valid as it was not in the original tuple type 

Edit: Since 3.4, typescript has changed the behavior of mapped types on array and tuples, so Readonly<[string, number]> is now equivalent to a readonly tuple readonly [string, number], so the errors are a bit different:

let readonlyArray: Readonly<[string, number]> = ["test", 1];
readonlyArray.concat = ()=> {} // Not valid, concat is readonly 
readonlyArray.push(1); // This is not valid, no push method anymore
readonlyArray[1] =  ""; // Invalid we cannot change a property by indexing 
readonlyArray[3] =  ""; // Invalid now tuple length preserved

</Edit>

ReadonlyArray<T> is a true readonly array that does not have any methods that can change the array. In your case any item of the array can be either a string or a number:

let readonlyArray2: ReadonlyArray<string | number> = ["test", 1, 1];
readonlyArray2.concat = ()=> []; // Valid we can set the concat property on the object 
readonlyArray2.push(1) // No push method, invalid
readonlyArray2[1] =  ""; // Invalid it is read only 
readonlyArray2[3] =  ""; // Invalid it is read only 

Upvotes: 12

Aravind
Aravind

Reputation: 41571

Readonly

  • The Readonly<T> is not necessarily an array; that expects any type <T>
  • To make the Readonly to store an array of values, the type <T> should be an [T]
  • Does not contain mutable methods

    let readonlyArray: Readonly<string| number> = ["test", 1, 1];    // not assignable
    
    let readonlyArray: Readonly<[string| number]> = ["test", 1, 1]; // assignable
    

ReadonlyArray

  • The ReadonlyArray accepts by default an array
  • Contains mutable methods

    let readonlyArray: ReadonlyArray<string| number> = "test";      // not assignable
    
    let readonlyArray: ReadonlyArray<string| number> = ["test"];   // assignable
    

Upvotes: 2

Related Questions