GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||
GeezerVison is showing github.com — Readonly properties and index signatures by ahejlsberg · Pull Request #6532 · microsoft/TypeScript Conversation
Member
This PR adds support for readonly properties and index signatures as suggested in #12. Changes include:
Entities are implicitly read-only in several situations:
Some examples: interface Point { readonly x: number; readonly y: number; } var p1: Point = { x: 10, y: 20 }; p1.x = 5; // Error, p1.x is read-only var p2 = { x: 1, y: 1 }; var p3: Point = p2; // Ok, read-only alias for p2 p3.x = 5; // Error, p3.x is read-only p2.x = 5; // Ok, but also changes p3.x because of aliasing class Foo { readonly a = 1; readonly b: string; constructor() { this.b = "hello"; // Assignment permitted in constructor } } // Read-only view of Array<T> with all mutating methods removed interface ReadonlyArray<T> { readonly [x: number]: T; readonly length: number; toString(): string; toLocaleString(): string; concat<U extends ReadonlyArray<T>>(...items: U[]): T[]; concat(...items: T[]): T[]; join(separator?: string): string; slice(start?: number, end?: number): T[]; indexOf(searchElement: T, fromIndex?: number): number; lastIndexOf(searchElement: T, fromIndex?: number): number; every(callbackfn: (value: T, index: number) => boolean, thisArg?: any): boolean; some(callbackfn: (value: T, index: number) => boolean, thisArg?: any): boolean; forEach(callbackfn: (value: T, index: number) => void, thisArg?: any): void; map<U>(callbackfn: (value: T, index: number) => U, thisArg?: any): U[]; filter(callbackfn: (value: T, index: number) => boolean, thisArg?: any): T[]; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number) => T, initialValue?: T): T; reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U): U; reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number) => T, initialValue?: T): T; reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U): U; } let a: Array<number> = [0, 1, 2, 3, 4]; let b: ReadonlyArray<number> = a; b[5] = 5; // Error, elements are read-only b.push(5); // Error, no push method (because it mutates array) b.length = 3; // Error, length is read-only a = b; // Error, mutating methods are missing Note that the The PR still needs tests, but I thought I'd get it up there for folks to take a look at.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Conflicts: src/compiler/parser.ts src/compiler/types.ts
Contributor
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this indexer not readonly?
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe because we don't want to break this code: enum SyntaxKind { Node, OtherNode } function dbgPrint(value: number, yourEnum: { [n: number]: string }) { console.log(yourEnum[value]); } // Would-be error, dbgPrint wants mutable index signature but enum has readonly signature dbgPrint(SyntaxKind.OtherNode, SyntaxKind);
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah right, because of the assignability rule. Makes sense.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's right. It's bit of a puzzle to ensure backwards compatibility, so there are actually two forms of read-only-ness in the new implementation:
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. That sounds like a good distinction.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As clarification, increment/decrement operator and any assignment to enum isn't allowed as enum type is read-only upon assignment? if that is the case, I think the error message should be updated.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Contributor
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
Contributor
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
|
There was an error while loading. Please reload this page.
|
[I apologize for this being very off-topic but since I was asked I felt I had no choice but answering here, the person who asked doesn't have a public email so there is no way for me to contact them personally] Yes, my personal impression is that they are very 'difficult' people to deal with, in the sense that they are putting as much energy into 'justifying' (sometimes dishonestly or irrationally) their actions and decisions to actually considering things openly and objectively when presented to them. They even do this on some very trivial subjects (e.g. you tell them they don't conform to the ES6 spec by practically disallowing inheritance of static accessors for ES5 targets and instead of listening and acknowledging the problem like a normal person would do, a group of team members just 'jumps' on you and starts to throw some strange and arbitrary ('canonical') justifications about performance consideration and dubious statistics there is '0%' anyone would ever want to do this.. well I did! and so did others who reported this problem, and probably many who didn't.. :( ). They put you in a situation where you have to be so eloquent and rational, to the point you have to literally spend dozens of hours into very carefully and rationally crafting a 'thesis' for something otherwise relatively trivial, just for them. And they on the other side are allowed to simply 'push' their opinions and twisted patterns of 'justification' arbitrarily without anyone saying anything. When you start challenging those patterns they would either ignore you or tell you you are intentionally 'wasting their time' with things that aren't important. They would also use their 'internal' understanding of the language and compiler by mentioning intricate things or concepts you don't know or completely understand and dishonestly use that against you. They take submitted ideas they like but they don't actually partake in real two-way conversations about it. They don't really involve the submitter of their personal ideas and insights, at least before they decide on their actions. And when/if they do inform back, they would condense it to a set of a few sentences that are not very useful or enlightening by themselves (or direct you to a set of design 'notes' that are very hard to extract anything useful from). You can't ask a (non-trivial) question because that's just 'wasting their time' (they don't do 'one on one'). If they don't like an idea, they would usually 'tank' and attack it mercilessly to the point of almost (or perhaps actually) insulting the person who submitted it. They almost never 'improve' on things suggested to them, at least not publicly. They would rather spend their time and 'smarts' in crafting careful arguments for justifying why they think someone are 'wrong' and they must be 'right' than taking a step back to seriously and objectively reconsider things, and eventually thank the participant for contributing something useful to the discussion. This has been my experience so far, anyway. I'm mostly referring here to the 2-3 members who reply to GitHub issues. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Is there any reason / chance to change that the generated code contains regular property assignment and not |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I agree with Ingvar Stepanyan (@RReverser) - on my team we frequently use TypeScript compiled code from (legacy)JavaScript applications - so keeping as many of those protections as possible would be very helpful. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Is this already available or only for TypeScript 2.0 (neither VS nor TypeScript Playground seem to understand it) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@Aides359 As usual with all the fresh stuff, you need to use |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@Aides359 I think the playground hosts the latest stable release. I recommend doing what Ingvar Stepanyan (@RReverser) suggests and additionally installing vscode and setting then |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Why disallow assignments in the other methods of a class? A Does the limitation exist for a technical reason? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
If that were allowed we'd have daily reports about "Bug: Why does TS let me mutate We discussed the notion of "public readonly, protected mutable" but opted not to simply due to complexity. You can already have a getter-only wrapper around a private variable, which achieves the same semantics at the cost of slightly increased class size. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
OK. You use the term |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I use this great feature for mutable preventing by the syntax highlighting. Thanks a lot for this! +++ |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
this is a horrible change, rendering this feature usless |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
simple use case that fails, I have my app about 1500 TS files thick, in this app I have an interface named Data that was intended to be immutable historically could not be forced being so With the readonly feature announced it was immediately clear that such enforcment can be imposed. However it turned out that there were a few places where Data was meant to be mutable. To address it the original Data interface was split into ReadOnlyData and WitableData, however it didn't help much due to the said decision. Details can bee seen in #13002. Bottom line is we are still not sure if Data is effectively mutable or not, despite applibg |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Anders Hejlsberg (@ahejlsberg) Correct me if I'm wrong, but the only reason interface compatibility checking on readonly is a breaking change is because of readonly being implicitly applied to everything. The tradeoff of worse soundness in return for saving the user some typing, especially when you now have mapped types, is not a good one IMO. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.