-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Narrow on element access of known property #10565
Conversation
Narrowing now happens for x['knownProperty'] as well as x.knownProperty
@RyanCavanaugh @ahejlsberg do you want to take a look? |
expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression); | ||
if (expr.kind === SyntaxKind.ElementAccessExpression) { | ||
const argument = (expr as ElementAccessExpression).argumentExpression; | ||
return argument.kind === SyntaxKind.StringLiteral || argument.kind === SyntaxKind.NumericLiteral || argument.kind === SyntaxKind.EnumMember; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the expr.expression should be, an identifier, this, a PopertyAccessExpression or ElementAccessExpression , so we should recursively call the function on the expression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should also add tests to multiple levels of elementAccess. a[0][1]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, multiple levels of property access don't work either. So I think this function should actually be even simpler until we fix that bug.
interface Square {
sub: { kind: "square; };
size: number;
}
// etc ...
function area(s: Shape) {
switch(s.sub.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
}
}
Nested element accesses are now supported. |
@mhegazy you started reviewing this change. Can you look at the new commits so it can go in? |
I ran a performance benchmark on the code compared to master. The standout difference was that Monaco (the online component that powers the playground) has a 6.85% slowdown in the checker, or 0.41 second. TFS has a small slowdown in the checker but it's not statistically significant. I'm trying to get github formatting to co-operate so I can show the actual table but haven't had any luck yet. |
As @mhegazy suggested, I tried the benchmark again, this time only narrowing string element accesses, not number accesses. The results are about the same. |
given the performance penalty vs. utility of this change, we will not be able to take it. |
Would it be possible to revise the decision on this PR 1.5 years since the original implementation? Will the performance impact be so critical now too? When a property has spaces or other no-standard characters, it is impossible to either define it or read its value via const config = {
param: 42,
"param 2": 43,
}
console.log(config.parammmmm); // <--- typo caught by the compiler
console.log(config["parammmmm 2"]); // <--- typo not caught |
i do not think the error you listed above has do with this PR. The issue here is that it is legal to index into any property using a string/numeric name. the result is an implicit |
I'm not sure that |
could this perhaps land behind a flag? or maybe just for numeric properties accessed via brackets?
|
I reconstituted the PR and found (1) a probably performance bug that it introduced in |
Can we have this behind a flag? I've had to add dozens of non-null assertions to fix this and would gladly take the 6.5% performance hit. |
I agree, the current behavior is unintuitive and should be fixed. |
For what it's worth, I've verified that For my use case, It's purported that #10530 is tracking the issue and #48335 is tracking new documentation for the current behavior and workarounds. |
Would it be possible for us to simply rebase this branch and rerun the benchmarks to get a clearer picture of the real-world performance? |
@sandersn, what do you think about the above question? Could we give this another try, please? |
One does not "simply" rebase a 7-year-old PR 😅 The example in the linked issue, and the example in this comment #10565 (comment), both now work. Can you clarify what you're looking for? |
Now as I am reading the purpose of this PR again, I certainly commented on the wrong one. I was trying to figure out why TS doesn't narrow down the type in this specific scenario. |
Fixes #10530
Narrowing now happens for
x['knownProperty']
the same way that it does forx.knownProperty