Last updated: Feb 27, 2024
Reading timeยท4 min
The "Function lacks ending return statement and return type does not include undefined" error occurs when not all code paths of a function with an explicit return type return a value.
To solve the error, return a value from all code paths or include undefined
in the function's return type.
Here is an example of how the error occurs.
// โ Error:๏ธ Function lacks ending return statement // and return type does not include 'undefined'.ts(2366) const getNumber = (): number => { if (Math.random() > 0.5) { return 100; } // ๐๏ธ No return value here ๐๏ธ };
We've explicitly
set the function's return type to
number
but
not all code paths return a value.
To solve the error, make sure to return a value from all of the function's code paths.
// โ Works now const getNumber = (): number => { if (Math.random() > 0.5) { return 100; } return 50; // ๐๏ธ all code paths return a value };
Even if the if
condition isn't met, a value of the correct type is returned.
catch()
blockThe error also occurs when using a try/catch
statement in a function for which
we've set a return type.
// โ Error:๏ธ Function lacks ending return statement // and return type does not include 'undefined'.ts(2366) const getPromise = async (): Promise<number> => { try { const result = await Promise.resolve(42); return result; } catch (err) { console.log(err); // ๐๏ธ no return value here ๐๏ธ } };
The issue is that we've typed the function to return Promise<number>
, so
TypeScript expects all calls to the function to return Promise<number>
, even
the ones that error out.
Use a union type to set the
function's return type to
Promise<number | undefined>
.
// โ Works now const getPromise = async (): Promise<number | undefined> => { try { const result = await Promise.resolve(42); return result; } catch (err) { console.log(err); return; } };
Now TypeScript knows that the function returns a Promise of type number
or
undefined
, which is an accurate representation of the function's return type.
When you get the return value of the function, use a
type guard to determine if it's a
number
or undefined
.
const getPromise = async (): Promise<number | undefined> => { try { const result = await Promise.resolve(42); return result; } catch (err) { console.log(err); return; } }; getPromise().then((value) => { if (typeof value === 'number') { // โ We know that value is number console.log(value.toFixed()); } });
A simple if
statement in which we used the
typeof operator serves as a type
guard.
TypeScript knows that the value is a number
in the if
block, so we can
safely access number-related built-in methods.
The third example shows how TypeScript is not always able to accurately determine the flow of a function.
// โ Error:๏ธ Function lacks ending return statement // and return type does not include 'undefined'.ts(2366) const getString = (): string => { if ('hello'.length === 5) { return 'hello'; } else if ('hello'.length === 6) { return 'hello'; } // ๐๏ธ TypeScript doesn't know that ๐๏ธ // getting here is impossible };
The string hello
has a length of 5
, so we know that the if
block will run
and we will always return the value hello
, but TypeScript doesn't know.
else if
statement with an else
statementTo solve this, we have to replace the ending else if
statement with an else
or simply remove the condition.
The following 2 examples are the same.
// โ Works now const getString = (): string => { if ('hello'.length === 5) { return 'hello'; } else { return 'bye'; } };
Or remove the else
block completely.
// โ Works now const getString = (): string => { if ('hello'.length === 5) { return 'hello'; } return 'bye'; };
Either way, TypeScript is now able to determine that all of the function's code
paths return a value of type string
.
A common cause of the error is when we return a value from an inner function or a callback and think that the value also gets returned from the outer function.
// โ Error:๏ธ Function lacks ending return statement // and return type does not include 'undefined'.ts(2366) const getString = (): string => { if ('hello'.length === 5) { return 'hello'; } function inner() { return 'bye'; } inner(); };
The inner
function returns a string
, however, returning a value from a
nested function doesn't mean the value gets returned from the outer function.
If you are in a similar situation, make sure to return the result of calling the inner function.
// โ Works now const getString = (): string => { if ('hello'.length === 5) { return 'hello'; } function inner() { return 'bye'; } return inner(); };
You can learn more about the related topics by checking out the following tutorials: