Repository: TypeScript
Issue: Immutable-By-Default Flags
Labels: Suggestion,Awaiting More Feedback

## Search Terms

readonly, default, immutable

## Suggestion

Adding flags under the `strict` umbrella to default to immutability in different cases, and a new `mutable` keyword.

## Use Cases

I'm creating this issue as a _parent issue_ to track a couple of issues that already exist for specific cases:
- Class methods: https://github.com/microsoft/TypeScript/issues/22315, https://github.com/microsoft/TypeScript/issues/22315#issuecomment-400708470 in particular
- Arrays: https://github.com/microsoft/TypeScript/issues/32467
- Interfaces: No issue yet, left a comment in https://github.com/microsoft/TypeScript/issues/32467#issuecomment-519333922
- https://github.com/microsoft/TypeScript/issues/21152

Off of the top of my head, these flags would have some direct advantages:
- They clearly state the intention of the whole project in regards to mutability
- It's very common for new members of teams to forget to add the `readonly` keyword or use `T[]` rather than `ReadonlyArray<T>` accidentally. Defaulting to immutability would help prevent these accidents, and a `mutable` keyword would be easy to find by `tslint` or even a simple `grep`, to automatically request review in PRs or leave an automated comment `this PR introduces mutation`. 

## Examples

Examples should probably live in the _children_ GitHub issues, but I'm copying here [my comment](https://github.com/microsoft/TypeScript/issues/32467#issuecomment-519333922) for a quick example:

```ts
interface T {
  n: number // immutable
  mutable s: string // mutable
}

const o: T = {
  n: 42,
  s: 'hello world',
}

o.n = 43 // error
o.s = '👋🌎' // ok
```

## Checklist

My suggestion meets these guidelines:

* [ ] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).

## Backwards Compatibility

@AnyhowStep made an interesting [comment on this issue](https://github.com/microsoft/TypeScript/issues/32758#issuecomment-569369439).

Basically this feature wouldn't be any problem for applications, but it could be problematic for libraries, as the emitted `.d.ts` may be imported from a library/application that isn't using this flag or is using an older TS version.

Possible solutions:
- A pre-processor directive (https://github.com/microsoft/TypeScript/issues/32758#issuecomment-569369439)
- Always emitting `d.ts` with `readonly`, never `mutable` (possibly behind another flag?)
- [downlevel-dts](https://github.com/sandersn/downlevel-dts)

## Records and Tuples

The [Record and Tuple proposal](https://github.com/tc39/proposal-record-tuple) has reached stage 2, so it may be arriving to TS soon-ish. It seems closely related to this issue, but I don't think it fully addresses it.

## `readonly interface`

The possibility of using the `readonly` keyword for an entire `interface` has been suggested in A cheaper, easier to implement middle ground could be https://github.com/microsoft/TypeScript/issues/21152.

```ts
readonly interface State {
    prop1: string;
    prop2: string;
    ...
    prop22: string;
}
```

This would probably be a much cheaper and less disruptive feature to implement, and could be a great starting point.