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 — Local types by ahejlsberg · Pull Request #3266 · microsoft/TypeScript Conversation
Member
This PR implements support for local class, interface, enum, and type alias declarations. For example: function f() { enum E { A, B, C } class C { x: E; } interface I { x: E; } type A = I[]; let a: A = [new C()]; a[0].x = E.B; } Local types are block scoped, similar to variables declared with function f() { if (true) { interface T { x: number } let v: T; v.x = 5; } else { interface T { x: string } let v: T; v.x = "hello"; } } The inferred return type of a function may be a type declared locally within the function. It is not possible for callers of the function to reference such a local type, but it can of course be matched structurally. For example: interface Point { x: number; y: number; } function getPointFactory(x: number, y: number) { class P { x = x; y = y; } return P; } var PointZero = getPointFactory(0, 0); var PointOne = getPointFactory(1, 1); var p1 = new PointZero(); var p2 = new PointZero(); var p3 = new PointOne(); Local types may reference enclosing type parameters and local class and interfaces may themselves be generic. For example: function f1() { function f() { class C<X, Y> { constructor(public x: X, public y: Y) { } } return C; } let C = f(); let v = new C(10, "hello"); let x = v.x; // number let y = v.y; // string } function f2() { function f<X>(x: X) { class C<Y> { public x = x; constructor(public y: Y) { } } return C; } let C = f(10); let v = new C("hello"); let x = v.x; // number let y = v.y; // string } function f3() { function f<X, Y>(x: X, y: Y) { class C { public x = x; public y = y; } return C; } let C = f(10, "hello"); let v = new C(); let x = v.x; // number let y = v.y; // string }
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'd rather this be split into more Alternatively, break each subexpression onto its own line and explain each of them independently. For instance: // We've found something in the 'locals' table, but we are sensitive to location in whether it is valid to use // this entity. // - A non-type entity (i.e. values, namespaces, and aliases) is unconditionally resolved. // - A type parameters are visible throughout the entirety of a declaration, and are resolved. // - A local type found in any declaration *other than a function* can be considered resolved. // - A local types found in a function is only resolved if it was used *within the body of the function*. if (!(meaning & SymbolFlags.Type) || !(result.flags & (SymbolFlags.Type & ~SymbolFlags.TypeParameter)) || !isFunctionLike(location) || lastLocation === (<FunctionLikeDeclaration>location).body) {
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. In general I think it is perfectly fine (and often preferable) to have multi-line boolean expressions instead of multiple I do agree that in this case putting each condition on a separate line might make sense.
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 disagree. I think that multiple if statements are actually simpler. They allow you to examine each clause, one at a time. They let each clause be simple explained. They do not require you to think through multiple different forms of boolean expressions in each clause. Some minds (mine included) tend to have the problem where we see one expression, and then 'stamp' what we saw there on the next in a complicated clause. So if one expression does At this point, we've been using this code for around a year at this point, and there are still comments/complaints on the PRs about the clarity of the code. At this point, i think we should accept that these constructs are difficult for many team members to read, and we should err on the side of making the code as maintainable as possible for the team as a whole.
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. We'll just have to disagree here. If the team has problems reading multi-line boolean expressions then I think we have a bigger problem. You're advocating turning simple and functional boolean expressions into multiple imperative if statements with temporary variables. I think that is exactly the wrong way to go. Whenever I see those I always wonder if I'm missing something subtle (which imperative code is full of), because otherwise it would just be written as a simple boolean expression.
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 am confused about the purpose of the getStatementFlags approach. Why is it better than having isStatement and isModuleElement just make the decisions for themselves? Is it so that there can be just one place (instead of two) to account for all the node kinds here, so we don't forget any?
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. The problem is modifiers. When modifiers are present we can't tell from the first token what we're looking at. So we need to look ahead, but we don't want to do that more than once. And, as you say, when everything is in one place we're certain that there won't be any subtle differences.
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.
Member
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. Is this for anonymous class expressions?
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. No, it's for the anonymous type created for the static side of a class.
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 yes, because previously the static side of a class could never get instantiated.
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.
Contributor
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
Anders Hejlsberg (ahejlsberg)
added a commit
that referenced
this pull request
Local types
Closed
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
ReviewersNo reviewsUh oh!
There was an error while loading. Please reload this page. AssigneesNo one assignedLabels
None yet
ProjectsMilestoneNo milestoneDevelopmentSuccessfully merging this pull request may close these issues. Allow enums in local scopes Allow local interface definitionUh oh!
There was an error while loading. Please reload this page. Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later. | ||||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |