Typescript: Default to ReadonlyArray

Created on 18 Jul 2019  Β·  10Comments  Β·  Source: microsoft/TypeScript

Search Terms

ReadonlyArray, default

Suggestion

By default type for array is inferred as Array. It would be better to default to a more strict ReadonlyArray and if programmer needs mutability β€” he would explicitly state so. Could be a tsconfig option to not introduce a breaking change.

Use Cases

readonly value = [0, 1, 2, 3]; // <-- type number[] here

Examples

readonly value = [0, 1, 2, 3];
readonly mutableValue: Array<number> =  [0, 1, 2, 3];

Checklist

My suggestion meets these guidelines:

  • [βœ“] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [βœ“] This wouldn't change the runtime behavior of existing JavaScript code
  • [βœ“] This could be implemented without emitting different JS based on the types of the expressions
  • [βœ“] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [βœ“] This feature would agree with the rest of TypeScript's Design Goals.
Awaiting More Feedback Suggestion

Most helpful comment

Having a flag which will turn on "assume everything is read only" would be great!

I'm using readonly in all the places and it's too noisy. I would prefer mutable flag for places where I do need mutation which I don't in 99% of the time.

All 10 comments

Are you saying you want,

//ts
export const arr = [1,2,3];

To emit,

//.d.ts
export const arr : readonly number[];

?

@AnyhowStep I'm not familiar with the syntax you used in your .d.ts. I want a tcsconfig option for

//ts
export const arr = [1,2,3];

to emit

//.d.ts
export const arr: ReadonlyArray<number>;
class Test {
    readonly value = [0, 1, 2, 3] as const; // <-- type `readonly [0, 1, 2, 3]` here
}

I see. Thanks @demensky so there's this (was not familiar with this feat):
https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#const-assertions
That's a bit shorter than explicitly stating ReadonlyArray but in terms of arrays I like never use mutability and very rarely do for objects, it would be great if I could force that thing on a tsconfig level like I can force things like strict null checks, no implicit any, strictPropertyInitialization, stuff like that.

EDIT: Maybe this issue can be turned into:

Option to default to as const for objects and arrays with added as mutable assertion for mutability

Do note there's a subtle difference - as const when applied to an array literal infers a tuple, not an array. At runtime tuples and arrays are the same of course, but there are differences in how the type system treats them.

It also infers the strictest possible type for each element (literal type) rather than the more general number or string, so that's something to keep in mind too.

@fatcerberus true, that's why I'm focusing on array and object since it wouldn't matter for them for the most part, and for numbers and strings we can just declare them as const and not let.

I'd like this feature, but TypeScript should remain intuitive to plain JavaScript users IMO, so it should live behind a -strict-array-immutability flag.

I'd also love to have this for interface properties, defaulting to readonly with a -strict-interface-immutability flag and having to mark mutable ones with a mutable keyword, as such:

interface T {
  n: number // immutable
  mutable s: string // mutable
}

const o: T = {
  n: 42,
  s: 'hello world',
}

o.n = 43 // error
o.s = 'πŸ‘‹πŸŒŽ' // ok

The interface is a separate suggestion and should probably live in its own GitHub issue, but it makes sense to mention it in this discussion since the semantics/syntax should be similar.

Related: https://github.com/microsoft/TypeScript/issues/22315, this comment in particular also requests a _flag under the strict umbrella_ for readonly-by-default.

Good idea! However, I would like it also for interface properties. At the moment, my code has too much readonly keywords.

readonly value = [1, 2, 3, 4, 5] means only that you cant reassign value
But you can add more elements into value, so value.push(6) works fine

Having a flag which will turn on "assume everything is read only" would be great!

I'm using readonly in all the places and it's too noisy. I would prefer mutable flag for places where I do need mutation which I don't in 99% of the time.

Was this page helpful?
0 / 5 - 0 ratings