You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
add a flag to disable () => void being subtype of () => a #8584
unhandled Promise<r> (a result now or later) is a classic example, but it is also a misuse to ignore Optional<r> (a result or nothing) or Tried <r, e> (a result or an exception)
all in all TypeScript is clearly favoring OOP over FP being yet another mainstream languages with a low entry level
There are a lot of functions with infrequently-useful return values. They can't be declared as returning void, since you sometimes want to use the return, but it would be quite burdensome to have to use the void operator whenever you don't. Node.prototype.appendChild comes to mind.
Whether a return value is "ignorable" or not isn't just determined by its type, either. People ignore the number setTimeout returns (a timer ID) all the time, but ignoring the number Math.floor returns, for example, can only be a bug:
varx=3.14;Math.floor(x);console.log(x);// "Why isn't it 3?" ;)
So to properly detect bugs involving ignoring return values, the type system would have to distinguish between ignorable and unignorable return values, perhaps by intersection with void:
declarefunctionsetTimeout(...): number&void;// ignorabledeclarefunctionfloor(...): number;// not ignorable
It's an interesting idea, but one the TypeScript people would probably reject.
Reacted by Sean Vieira, Duan Yao, NN, Agostino Carandente, Suhair Zain, Arseniy Terekhin and Ahmed Gubara
People ignore the number setTimeout returns (a timer ID) this
if you are (like us) working on a serious UI heavy application with a possibility to cancel any long running opertaion you must never ignore it
for a jquery powered home page, sure go ahead
believe me the hassle of being exact about ignoring the return value is nothing compared to the benefits of being able to catch more bugs at compile time, if you value the quality and your time
this all comes down to an old idea of making typescript stricter to ones who needs it (minority): #274
I will bring it up for discussion. though I do nothing think we should be adding flags to change the behavior of the type system, unless it is a transitional phase (e.g. noImplictAny, strictNullChecks, etc..).
e.g. Array#reverse return value is always safe to ignore, but ignoring Array#concat's return value is 99.9% a bug (thank Array designers for confusing API design!)
Too cumbersome for the vast majority of people to enforce void func(); on all non-voidfuncs
We could do this if we had function attributes, but we don't
Reconsider if we get attributes or other metadata system that would enable this
Reacted by Sean Vieira, David Rodrigue, Stanislav Panferov, ZpdDG4gta, Kevin Ryan, Cosmin Ababei, Agostino Carandente, Samuel Bodin, Suhair Zain and Gjum
As I already said in #8240, this issue is must have to simplify work with all immutable data structures and immutable operations (concat is a good example of immutable operation). People quite often forget that they need to write
model = model.set('prop', 1)
instead of just
model.set('prop', 1)
And it's pretty hard to find the error in the large codebase. And it's also very annoying.
I came here from another issue which was discussing an option to mark a function such that it's return type cannot be unused. I'm unable to understand whether this issue is actually about it, so please forgive me if it isn't.
A useful scenario for the above mentioned feature is while using redux-thunk. We can create a thunk like subscribeToPlan(), but we might forget to actually dispatch it, leading to an error. This is usually not a problem when we create new thunks because we'll find that the new feature is not working as expected, but if we're migrating from a library which uses another convention to something like a thunk, we might miss a place if there are a lot of changes. If there was a way to mark a thunk such that it has to be used, we'd be able to catch them at compile time.
We've been spending hours dealing with bugs that would been caught with this check. as Simon Buchan (@simonbuchan) had pointed out, this language feature is available in a lot of languages, and some even have it turned on by default. e.g. Swift
Would really like to see TypeScript adding support to this as well.
Also, if anyone knows if there is any workaround currently?
Either being eslint, tslint or anything that can help mitigate this?
Reacted by Andrii Fidria, andrei, Carl Patenaude-Poulin, Suhair Zain, satoren, Gjum and Juan Campa
Instead of global flag could this be a new utility type than can be applied where we want?
At least it would not be breaking changes but still could help solve this issue in the long term
Like the opposite of readonly #24509
If specified return or param should be checked
With readonly combined with SideEffect you would be able to know that a value has changed or not,
and if it could be a mistake.
Invalid
varx=3.14;Math.floor(readonlyx);// WARN: "math.floor() do not modify the input but returns it, did you mean to use the result?"
varx={foo: 'bar'};x=modify(x: SideEffect<object>): any;// WARN: "compute() modifies the input but you reassigned the results to the original value, did you mean to check the input?"
varx={foo: 'bar'};modify(x: SideEffect<object>): any;// WARN: "compute() modifies the input but you never reuse it, did you mean to pass it by reference?"
I was directed here from #8240 ("Result value must be used") and I'm not sure why that one was closed and locked in favor of this issue, since both seem to be about different concepts.
This issue (coming from #8581) started out with a global compiler flag to disable assigning a non-void return type to a void return type, which (as RyanCavanaugh and mhegazy already pointed out in #8581/#8240) runs against the established understanding of assignability - it is indeed perfectly valid to ignore the result of many function calls, especially most existing JavaScript APIs.
#8240 is about marking individual functions, for example like bodinsamuel suggested, which presumably wouldn't require "function attributes" so it would be worth reconsidering.
That feature would be much less intrusive than a global change of compiler behavior.
It also fulfills these requirements:
It wouldn't be a breaking change in existing TypeScript / JavaScript code
It wouldn't change the runtime behavior of existing JavaScript code
It could be implemented without emitting different JS based on the types of the expressions
It isn't a runtime feature (e.g. new expression-level syntax)
Please clarify whether this issue is about the global flag or per-function flag, and if the former, please reopen #8240 as it is a different and reasonable feature, while this issue is clearly controversial due to its intrusive nature.
Actually, on second thought, "result must be used" is exactly the same as "pure" (or has such substantial overlap that it's not really needed to have both); #7770
The problem here is that it's changing useCallback to fix callback caring about a being used, because:
sometimes assuming that the result of a function might be ignored isn't safe
It's not really the best description for this issue, but I can't really agree with merging with pure either.
Here are some DOM examples of very-non-pure, but very-must-use functions:
// different results each time, but no use except for result:Date.now();crypto.randomBytes();// even after unwrapping promise, could return failure responsefetch();// locks the stream as a side-effect, but also useless without using the readerstream.getReader();
And in practice the changes for pure would be largely about checking pure function bodies, while must-use is about checking calls to must-use results, at least from it's approach in other languages.
If you like I could put this threads must-use specific detail into a fresh issue?
Activity
RyanCavanaugh commentedon May 12, 2016
Would we also ban function calls in expression statements unless those functions are
void?e.g. I imagine you have this problem
zpdDG4gta8XKpMCd commentedon May 12, 2016
yes, you are right, expression statements other than
voidare a major painzpdDG4gta8XKpMCd commentedon May 12, 2016
wish there was a flag that would require the
voidoperator with themzpdDG4gta8XKpMCd commentedon May 12, 2016
unhandled
Promise<r>(a result now or later) is a classic example, but it is also a misuse to ignoreOptional<r>(a result or nothing) orTried <r, e>(a result or an exception)all in all TypeScript is clearly favoring OOP over FP being yet another mainstream languages with a low entry level
jeffreymorlan commentedon May 13, 2016
There are a lot of functions with infrequently-useful return values. They can't be declared as returning
void, since you sometimes want to use the return, but it would be quite burdensome to have to use thevoidoperator whenever you don't.Node.prototype.appendChildcomes to mind.Whether a return value is "ignorable" or not isn't just determined by its type, either. People ignore the number
setTimeoutreturns (a timer ID) all the time, but ignoring the numberMath.floorreturns, for example, can only be a bug:So to properly detect bugs involving ignoring return values, the type system would have to distinguish between ignorable and unignorable return values, perhaps by intersection with
void:It's an interesting idea, but one the TypeScript people would probably reject.
zpdDG4gta8XKpMCd commentedon May 13, 2016
if you are (like us) working on a serious UI heavy application with a possibility to cancel any long running opertaion you must never ignore it
for a jquery powered home page, sure go ahead
believe me the hassle of being exact about ignoring the return value is nothing compared to the benefits of being able to catch more bugs at compile time, if you value the quality and your time
this all comes down to an old idea of making typescript stricter to ones who needs it (minority): #274
mhegazy commentedon May 13, 2016
is this the same as #8240?
zpdDG4gta8XKpMCd commentedon May 13, 2016
it's about rephrasing the last line in 3.11.3 Subtypes and Supertypes
Instad:
Should be:
mhegazy commentedon May 13, 2016
I will bring it up for discussion. though I do nothing think we should be adding flags to change the behavior of the type system, unless it is a transitional phase (e.g. noImplictAny, strictNullChecks, etc..).
RyanCavanaugh commentedon May 16, 2016
Some points from discussion
Array#reversereturn value is always safe to ignore, but ignoringArray#concat's return value is 99.9% a bug (thank Array designers for confusing API design!)void func();on all non-voidfuncss-panferov commentedon May 17, 2016
As I already said in #8240, this issue is must have to simplify work with all immutable data structures and immutable operations (
concatis a good example of immutable operation). People quite often forget that they need to writeinstead of just
And it's pretty hard to find the error in the large codebase. And it's also very annoying.
9 remaining items
phaux commentedon Sep 26, 2019
There should be a new strict compiler option which does either of these:
() => voidasunknown, or() => not voidto() => voidan errorSuhairZain commentedon Apr 9, 2020
I came here from another issue which was discussing an option to mark a function such that it's return type cannot be unused. I'm unable to understand whether this issue is actually about it, so please forgive me if it isn't.
A useful scenario for the above mentioned feature is while using redux-thunk. We can create a thunk like subscribeToPlan(), but we might forget to actually dispatch it, leading to an error. This is usually not a problem when we create new thunks because we'll find that the new feature is not working as expected, but if we're migrating from a library which uses another convention to something like a thunk, we might miss a place if there are a lot of changes. If there was a way to mark a thunk such that it has to be used, we'd be able to catch them at compile time.
zhigang1992 commentedon Apr 21, 2020
We've been spending hours dealing with bugs that would been caught with this check. as Simon Buchan (@simonbuchan) had pointed out, this language feature is available in a lot of languages, and some even have it turned on by default. e.g. Swift
Would really like to see TypeScript adding support to this as well.
Also, if anyone knows if there is any workaround currently?
Either being eslint, tslint or anything that can help mitigate this?
carlpaten commentedon Oct 7, 2020
F# has this turned on by default for all functions as well.
bodinsamuel commentedon Oct 9, 2020
Instead of global flag could this be a new utility type than can be applied where we want?
At least it would not be breaking changes but still could help solve this issue in the long term
Like the opposite of readonly #24509
If specified return or param should be checked
With
readonlycombined withSideEffectyou would be able to know that a value has changed or not,and if it could be a mistake.
Invalid
Valid
Gjum commentedon Jun 25, 2021
I was directed here from #8240 ("Result value must be used") and I'm not sure why that one was closed and locked in favor of this issue, since both seem to be about different concepts.
This issue (coming from #8581) started out with a global compiler flag to disable assigning a non-void return type to a void return type, which (as RyanCavanaugh and mhegazy already pointed out in #8581/#8240) runs against the established understanding of assignability - it is indeed perfectly valid to ignore the result of many function calls, especially most existing JavaScript APIs.
#8240 is about marking individual functions, for example like bodinsamuel suggested, which presumably wouldn't require "function attributes" so it would be worth reconsidering.
That feature would be much less intrusive than a global change of compiler behavior.
It also fulfills these requirements:
Please clarify whether this issue is about the global flag or per-function flag, and if the former, please reopen #8240 as it is a different and reasonable feature, while this issue is clearly controversial due to its intrusive nature.
RyanCavanaugh commentedon Jun 25, 2021
Considering this again, I think the solution to OP is straightforward:
() => undefinedIf you want a function that truly returns nothing, that type is
() => undefinedif you want a function whose return type you pledge to ignore, that type is
() => voidFor "result must be used", I guess we need a new issue; these two have become too interlinked. Feel free to open.
RyanCavanaugh commentedon Jun 25, 2021
Actually, on second thought, "result must be used" is exactly the same as "pure" (or has such substantial overlap that it's not really needed to have both); #7770
simonbuchan commentedon Jun 26, 2021
Ryan Cavanaugh (@RyanCavanaugh) I'm not sure I quite understand: are you suggesting that if the original code were:
that it is changed to:
here?
The problem here is that it's changing
useCallbackto fixcallbackcaring aboutabeing used, because:It's not really the best description for this issue, but I can't really agree with merging with pure either.
Here are some DOM examples of very-non-pure, but very-must-use functions:
And in practice the changes for pure would be largely about checking pure function bodies, while must-use is about checking calls to must-use results, at least from it's approach in other languages.
If you like I could put this threads must-use specific detail into a fresh issue?
abdulkareemnalband commentedon Jun 26, 2021
Ryan Cavanaugh (@RyanCavanaugh) can you reopen either #8240 or #29173 for return value must be used feature
simonbuchan commentedon Jun 26, 2021
Or either of those, I suppose!
RyanCavanaugh commentedon Jul 8, 2021
Reopened #8240
simonbuchan commentedon Jul 8, 2021
Ryan Cavanaugh (@RyanCavanaugh) (psst, you actually only unlocked it, you didn't actually reopen it)
RyanCavanaugh commentedon Jul 8, 2021
Oops, thanks!