Repository navigation
Function return value constraints #228
Description
Activity
This is an issue we have discussed a lot. The reasoning behind the current behavior is that a function with an explicitly declared non-void return type and no return statements is clearly suspicious (and therefore should be an error), but otherwise the function might simply be relying on the fact that JavaScript returns undefined when a function doesn't explicitly return a value. We would turn a lot of existing (and technically correct) JavaScript code into errors if we tightened this, so it would definitely have to be an opt-in similar to noImplicitAny.
Thank you for the response Anders.
Having an option to warn on functions with no return value of all code path by the compiler would be great, I can imagine this should be the default behavior of the compiler given that the problem at hand is with the existing js code.DanielRosenwasser commented
on Jul 24, 2014 MemberMore actionsAlso related is #162, which would also be a breaking change if amended.
RyanCavanaugh commented
on Jul 28, 2014 MemberMore actionsLinking this to #274. I'd like to see some set of nailed-down rules. Specifically:
- Does this apply to contextually-typed functions as well?
- Do we enforce that "all or none" return statements have expressions?
- Is this intermixable with a "must return on all codepaths" rule?
This check is very important when working with promises, because people sometimes forget to return a promise, thus breaking a promise chain. Consider this sample:
var q = require("q"); var d = q.defer(); function f1() { return q("the first value"); } function f2() { process.nextTick(() => { d.resolve(); console.log("2"); }); return d.promise; } f1() .finally(function() { return f2(); }) .then(x => console.log("end: " + x)); console.log("1");If you execute it, the result is:
1 2 end: the first valueNow, lets assume, a programmer makes a mistake and forgets to return the result of f2:
.finally(function() { f2(); })The result is
1 end: the first value 2This mistake is very unfortunate. It is very easy to be made, especially when coding under pressure; is very easy to be missed on code reviews; tslint and friends does not complain; and its asynchronous nature allows it to slip through the manual and automated testing. The code even mostly works in production, except when it mysteriously does not. Considering how important promises and async/await become, I think it is worthy implementing this check behind an opt-in flag.
Reacted by Per Lundberg👍 for Todor Totev (@teobugslayer) 's suggestion
your wish is my command
declare function foo(s: (x: boolean) => number); foo((x): number => { if (x) return 1; })
compiling with current master bits
v2m@v2m-ThinkPad-W520:~/sources/TypeScript$ node built/local/tsc.js test.ts --noImplicitReturns test.ts(3,10): error TS7030: Not all code paths return a value.Reacted by Per LundbergVladimir Matveev (@vladima), I assume this will be released in typescript 1.8, is this correct?
Yes
Great news, thanks you!
Vladimir Matveev (@vladima) Great!
Vladimir Matveev (@vladima) does this page need to be updated to reflect this change?
It will be updated before the release
I've tested with this code
var q = require("q"); async function f3(): Promise<any> { }and it was successfully compiled without errors using this command line
node_modules\.bin\tsc index-async.ts --module commonjs --noImplicitReturns --target ES6I am using typescript by installing
npm i typescript@next.Is this expected?
currently it is by design,
anyas promised type (and as return type) suppressesnoImplicitReturncheckI see, thanks for the explanation.
I am very glad. Great work.
Should this issue be closed now?
thanks Alex Eagle (@alexeagle). closing.
- addedFixedA PR has been merged for this issueA PR has been merged for this issueand removedNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.
on Mar 3, 2016 Coming in "a bit" late to the party, thanks a lot for adding this option. As someone who is slowly but steadily learning TypeScript but with a strong background in the "implicit return" world of Ruby and CoffeeScript, this seems to be a bug I often make: forgetting to type out the
returnstatement, and without this setting, this is valid (but of course malfunctioning!) TypeScript code. Being able to set this setting intsconfig.jsonis great since it helps me avoid these kind of silly errors.So, great work Vladimir Matveev (@vladima) and the rest of you, thanks a lot.
A question: If I am declaring a method or a lambda type which must return a value, but it can return "any kind of value", is the correct way then to say that the return type is
Object? I.e. like this:function sql(callback: (h: Handle) => Object): Object { // ... }
Or is there some other, more correct way to do it? (As previously alluded, I willingly admit: I am not a Javascript nor TypeScript expert, yet. 😄)
In the example above, suppose I want to support an
undefinedreturn value, would this be the correct approach?function SomeMethod(): number | undefined { if (false) return 1; }What if I'm creating an interface and want to indicate that a function can return a value of a certain type or not at all (
undefined)? Would I have to includevoid?SomeMethod: () => number | undefined | void;- locked and limited conversation to collaborators
on Jul 30, 2018
TypeScript compiler allows to define a function marked explicitly with a return type, with code branches which lead to an inconclusive return value!
I know It is valid in JavaScript function not to return a value on all code path, however in TypeScript being a javascript typed superset, I can imagine having a poor written function [without return value on all code path] could potentially break other codes and I'm talking null-references, type mismatch,
NaN, ...I believe when using TypeScript code in an explicitly typed expression, no-one needs all the ugly plumbings, input or type validation,
undefinedchecking, ... One needs to be sure to write a code that couldn't break the way a dynamic language like javascript could!The following is a valid JavaScript code and it could compile within TypeScript:
When you explicitly mention that the method has a return value, the compiler throw an error:
However it is not the case when the function does not return in all code path, and I don't understand if this is by design why bother preventing above code from compiling in the first place!
The followings are all wrong in a typed context yet the compiler ignores them as a valid code: