microsoft / microsoft/TypeScript
Double initializing a `readonly` field should not be allowed
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
### 🔎 Search Terms
readonly double twice initializer
### 🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about initializers?
### ⏯ Playground Link
https://www.typescriptlang.org/play/?#code/MYGwhgzhAEBiD29oG8BQ0PQE4FMwBN4A7EAT2gCMwsAuaCAFywEsiBzaAXmgHJXmGzMCGYAvHFmgBGHgG5U6TMGKMsAV2AN4WABQBKFIsyYGAC2YQAdFUnc+RAUJHjJAJjlHoAX1Q-Uyogh4EBxLEHg2HSIcAHc4RH1raj1ZIA
### 💻 Code
```ts
class Foo {
readonly bar: string = 'initializer 1';
constructor() {
this.bar = 'initializer 2';
}
}
console.log(new Foo().bar);
```
### 🙁 Actual behavior
This compiles successfully despite overwriting a `readonly` field. This breaks expectations around `readonly`. If `Foo` happens to be a very large class and I only look at `readonly bar: string = 'initializer 1';` in isolation, I would expect any other line which reads `bar` to see `initializer 1`. However this is not a safe assumption because I need to check in the constructor to ensure it doesn't overwrite my `readonly` field.
### 🙂 Expected behavior
I expected a compiler error. TS should only allow _initializing_ `readonly` fields in a constructor, not overwriting a field which has already been initialized.
### Additional information about the issue
I get that we need `readonly` fields to be assignable in the constructor, but it feels like a bug to me that this is allowed when the field has already been initialized prior to the constructor. `readonly` should require a field initializer _xor_ a constructor initializer. Having both is invalid IMHO.
You can make the same argument that double initializing in the constructor should be invalid too:
```typescript
class Foo {
readonly bar: string;
constructor() {
this.bar = 'initializer 1';
this.bar = 'initializer 2'; // Should maybe error? Doesn't today.
}
}
```
But I understand that control flow analysis gets a lot more complicated in the constructor WRT `readonly` and might be considered a different feature with different priority.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the linked TypeScript Playground examples and compare the field-initializer case with the constructor-only double-assignment case. The change is done when the first example produces a compiler error for assigning to the already initialized readonly field, with the requested behavior covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100