-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Assume parameters are const
for the purposes of control flow analysis
#10180
Comments
Discussed alternative was to treat function expression as if they are always immediately invoked, which is obviously possibly-wrong for other reasons |
I wonder if you have considered the idea of annotating callback parameters as async(non-immediate) and default on sync(immediate)? Immediate case: function doSomething(callback: () => any) {
callback();
}
function fn(x: number|string) {
if (typeof x === 'number') {
doSomething(() => x.toFixed()); // No error.
}
} Non-immediate case: function doSomething(callback: async () => any) {
setTimeout(callback, 0);
}
function fn(x: number|string) {
if (typeof x === 'number') {
doSomething(() => x.toFixed()); // Error x is 'number|string'
}
} Sync callbacks is only assignable to sync callbacks and vice versa for Async callbacks: function doSomething(callback: () => any) {
setTimeout(callback, 0); // Error a sync callback is not assignable to an async one.
} function doSomething1(callback: () => any) {
callback();
}
function doSomething2(callback: () => any) {
doSomething1(callback); // No error
} Though re-using |
@tinganho what about all the callback signatures already declared in |
@yortus what about a classic solution, add a flag: Defaulting on async with no assignment checks as it is today with. And add a flag |
They will love that 😉 🎏 🎌 🇺🇸 |
(clears the throat) #7770 might be related somehow, despite it is widely believed that
|
An easy solution would be to add a flag that all parameters are const (which is a good programming practice anyway), e.g. I think there are multiple merits of this solution:
|
Simply add a flag :) The design team might need to seriously consider switching to a flag-driven-development paradigm. |
Proposal: Allow for the first 64 compiler flags to be specified as an integer literal. Then people can just be like "Oh I'm using TypeScript variant 41956651792133412" and then only merge codebases if they have compatible flags. |
@gcnew the problem with flags is that in order to handle them mathematically correctly you need to consider all 2^N cases where N - is the total number of flags. Example, say there were 2 flags already
Now here comes you and say, hey, let's add another one, because we need it:
the alternative is not to be 100% correct by dropping some cases from considerations, which may or may not lead to serious bugs and your own frustration think about it |
Though in most situations it is either add a flag or break someone else code. I dislike both cases, but faced with that situation I would rather add a flag than to break someone's code. That being said, whatever solution you cook up here it could also be baked into |
The combinatorial explosion of flags seems inevitable in a monolithic tool that has wide and ever-growing variety of use-cases and is called on to support them all, even when some demands are contradictory. The alternative is to build in extensibility (#6508) and let people choose the compile-time plugins they need instead of demanding flags in core. And they can write their own plugins too. Babel has gone that way. Clearly extensibility has it's own problems too, as anyone familiar with babel can attest. |
...or do a flag cleanup at the cost of breaking some backwards compatibility. ** sorry for the off-topic |
@Aleksey-Bykov Yes, I do agree that introducing flags adds a disproportionate amount of complexity. Especially true for logic-heavy flags. Luckily it's not the case with const params as it should be handled with ease on parser level. There is no explosion of logic - parameters are just tagged as I was thinking the same as what @tinganho proposes - maybe it could be a part of |
Returning to the original topic... I think a reasonable compromise here would be to consider parameters |
Reference issue: #7719.
We currently consider this code to be invalid:
because the callback given to
doSomething
might be executed "later" and there "might be" (please ignore for the purposes of this issue the fact that there isn't) an assignment tox
which invalidates the type guard.The recommended workaround is to write
which is annoying/silly/undiscoverable. A proposed change is to allow e.g.
function fn(const x: number|string
but this is cumbersome given that the vast majority of parameters are not reassigned.For the purposes of control flow analysis, a simpler and more understandable solution is to assume that parameters are
const
. Assignments would still be allowed, but treating them asconst
(again, only for the purposes of control flow analysis) means we would optimistically assume that e.g.doSomething
's callback is immediately invoked, which is going to be effectively correct the great majority of the time in cases where it matters.The text was updated successfully, but these errors were encountered: