Requires a return statement (or non-undefined
Promise resolve value)
be present in a
function body if a @returns
tag (without a void
or undefined
type)
is specified in the function's JSDoc comment block.
Will also report @returns {void}
and @returns {undefined}
if exemptAsync
is set to false
and a non-undefined
value is returned or a resolved value
is found. Also reports if @returns {never}
is discovered with a return value.
Will also report if multiple @returns
tags are present.
exemptGenerators
- Because a generator might be labeled as having aIterableIterator
@returns
value (along with an iterator type corresponding to the type of anyyield
statements), projects might wish to leverage@returns
in generators even without areturn
statement. This option is thereforetrue
by default intypescript
mode (in "jsdoc" mode, one might be more likely to take advantage of@yields
). Set it tofalse
if you wish for a missingreturn
to be flagged regardless.exemptAsync
- By default, functions which return aPromise
that are not detected as resolving with a non-undefined
value andasync
functions (even ones that do not explicitly return a value, as these are returning aPromise
implicitly) will be exempted from reporting by this rule. If you wish to insist that onlyPromise
's which resolve to non-undefined
values orasync
functions with explicitreturn
's will be exempted from reporting (i.e., thatasync
functions can be reported if they lack an explicit (non-undefined
)return
when a@returns
is present), you can setexemptAsync
tofalse
on the options object.reportMissingReturnForUndefinedTypes
- Iftrue
and no return or resolve value is found, this setting will even insist that reporting occur withvoid
orundefined
(including as an indicatedPromise
type). Unlikerequire-returns
, with this option in the rule, one can discourage the labeling ofundefined
types. Defaults tofalse
.
Context | ArrowFunctionExpression , FunctionDeclaration , FunctionExpression |
Tags | returns |
Aliases | return |
Options | exemptAsync , exemptGenerators , reportMissingReturnForUndefinedTypes |
Recommended | true |
The following patterns are considered problems:
/**
* @returns
*/
function quux (foo) {
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @return
*/
function quux (foo) {
}
// Settings: {"jsdoc":{"tagNamePreference":{"returns":"return"}}}
// Message: JSDoc @return declaration present but return expression not available in function.
/**
* @returns
*/
const quux = () => {}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {undefined} Foo.
* @returns {String} Foo.
*/
function quux () {
return foo;
}
// Message: Found more than one @returns declaration.
const language = {
/**
* @param {string} name
* @returns {string}
*/
get name() {
this._name = name;
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
class Foo {
/**
* @returns {string}
*/
bar () {
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns
*/
function quux () {
}
// Settings: {"jsdoc":{"tagNamePreference":{"returns":false}}}
// Message: Unexpected tag `@returns`
/**
* @returns {string}
*/
function f () {
function g() {
return 'foo'
}
() => {
return 5
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {Promise<void>}
*/
async function quux() {}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false}]
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {IterableIterator<any>}
*/
function * quux() {}
// Settings: {"jsdoc":{"mode":"jsdoc"}}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {IterableIterator<any>}
*/
function * quux() {}
// Settings: {"jsdoc":{"mode":"typescript"}}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptGenerators":false}]
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {Promise<void>}
*/
function quux() {
return new Promise((resolve, reject) => {})
}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false}]
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {Promise<void>}
*/
function quux() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
});
})
}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false}]
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* Description.
* @returns {string}
*/
async function foo() {
return new Promise(resolve => resolve());
}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false}]
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* Description.
* @returns {void}
*/
async function foo() {
return new Promise(resolve => resolve());
}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false,"reportMissingReturnForUndefinedTypes":true}]
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns { void } Foo.
*/
function quux () {}
// "jsdoc/require-returns-check": ["error"|"warn", {"reportMissingReturnForUndefinedTypes":true}]
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {never} Foo.
*/
function quux () {
return undefined;
}
// Message: JSDoc @returns declaration set with "never" but return expression is present in function.
/**
* @returns {never}
*/
function quux (foo) {
return foo;
}
// Message: JSDoc @returns declaration set with "never" but return expression is present in function.
/**
* Reads a test fixture.
*
* @param path The path to resolve relative to the fixture base. It will be normalized for the
* operating system.
*
* @returns The file contents as buffer.
*/
export function readFixture(path: string): void;
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* Reads a test fixture.
*
* @param path The path to resolve relative to the fixture base. It will be normalized for the
* operating system.
*
* @returns The file contents as buffer.
*/
export function readFixture(path: string);
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {SomeType}
*/
function quux (path) {
if (true) {
return;
}
return 15;
};
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* Reads a test fixture.
*
* @param path The path to resolve relative to the fixture base. It will be normalized for the
* operating system.
*
* @returns The file contents as buffer.
*/
export function readFixture(path: string): void {
return;
};
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {true}
*/
function quux () {
if (true) {
return true;
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {true}
*/
function quux () {
if (true) {
} else {
return;
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {true}
*/
function quux (someVar) {
switch (someVar) {
case 1:
return true;
case 2:
return;
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {boolean}
*/
const quux = (someVar) => {
if (someVar) {
return true;
}
};
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {true}
*/
function quux () {
try {
return true;
} catch (error) {
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {true}
*/
function quux () {
try {
return true;
} catch (error) {
return true;
} finally {
return;
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {true}
*/
function quux () {
if (true) {
throw new Error('abc');
}
throw new Error('def');
}
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {SomeType} Baz.
*/
function foo() {
switch (true) {
default:
switch (false) {
default: return;
}
return "baz";
}
};
// Message: JSDoc @returns declaration present but return expression not available in function.
/**
* @returns {number}
*/
function foo() {
let n = 1;
while (n > 0.5) {
n = Math.random();
if (n < 0.2) {
return n;
}
}
}
// Message: JSDoc @returns declaration present but return expression not available in function.
The following patterns are not considered problems:
/**
* @returns Foo.
*/
function quux () {
return foo;
}
/**
* @returns {string} Foo.
*/
function quux () {
return foo;
}
/**
*
*/
function quux () {
}
/**
* @returns {SomeType} Foo.
*/
const quux = () => foo;
/**
* @returns {undefined} Foo.
*/
function quux () {}
/**
* @returns { void } Foo.
*/
function quux () {}
/**
* @returns {Promise<void>}
*/
async function quux() {}
/**
* @returns {Promise<void>}
*/
const quux = async function () {}
/**
* @returns {Promise<void>}
*/
const quux = async () => {}
/**
* @returns Foo.
* @abstract
*/
function quux () {
throw new Error('must be implemented by subclass!');
}
/**
* @returns Foo.
* @virtual
*/
function quux () {
throw new Error('must be implemented by subclass!');
}
/**
* @returns Foo.
* @constructor
*/
function quux () {
}
/**
* @interface
*/
class Foo {
/**
* @returns {string}
*/
bar () {
}
}
/**
* @record
*/
class Foo {
/**
* @returns {string}
*/
bar () {
}
}
// Settings: {"jsdoc":{"mode":"closure"}}
/**
* @returns {undefined} Foo.
*/
function quux () {
}
/**
* @returns {void} Foo.
*/
function quux () {
}
/**
* @returns {void} Foo.
*/
function quux () {
return undefined;
}
/**
* @returns {never} Foo.
*/
function quux () {
}
/**
* @returns {void} Foo.
*/
function quux () {
return;
}
/**
*
*/
function quux () {
return undefined;
}
/**
*
*/
function quux () {
return;
}
/**
* @returns {true}
*/
function quux () {
try {
return true;
} catch (err) {
}
return true;
}
/**
* @returns {true}
*/
function quux () {
try {
} finally {
return true;
}
return true;
}
/**
* @returns {true}
*/
function quux () {
try {
something();
} catch (err) {
return true;
}
return true;
}
/**
* @returns {true}
*/
function quux () {
switch (true) {
case 'abc':
return true;
}
return true;
}
/**
* @returns {true}
*/
function quux () {
for (const i of abc) {
return true;
}
return true;
}
/**
* @returns {true}
*/
function quux () {
for (const a in b) {
return true;
}
}
/**
* @returns {true}
*/
function quux () {
for (const a of b) {
return true;
}
}
/**
* @returns {true}
*/
function quux () {
loop: for (const a of b) {
return true;
}
}
/**
* @returns {true}
*/
function quux () {
for (let i=0; i<n; i+=1) {
return true;
}
}
/**
* @returns {true}
*/
function quux () {
while(true) {
return true
}
}
/**
* @returns {true}
*/
function quux () {
do {
return true
}
while(true)
}
/**
* @returns {true}
*/
function quux () {
if (true) {
return true;
}
return true;
}
/**
* @returns {true}
*/
function quux () {
var a = {};
with (a) {
return true;
}
}
/**
* @returns {true}
*/
function quux () {
if (true) {
return true;
} else {
return true;
}
return true;
}
/**
* @returns {Promise<number>}
*/
async function quux() {
return 5;
}
/**
* @returns {Promise<number>}
*/
async function quux() {
return 5;
}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false}]
/**
* @returns {Promise<void>}
*/
function quux() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(true);
});
})
}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptAsync":false}]
/**
* Description.
* @returns {void}
*/
async function foo() {
return new Promise(resolve => resolve());
}
// "jsdoc/require-returns-check": ["error"|"warn", {"reportMissingReturnForUndefinedTypes":true}]
/**
* @returns { void } Foo.
*/
function quux () {
return undefined;
}
// "jsdoc/require-returns-check": ["error"|"warn", {"reportMissingReturnForUndefinedTypes":true}]
/**
* @returns { string } Foo.
*/
function quux () {
return 'abc';
}
// "jsdoc/require-returns-check": ["error"|"warn", {"reportMissingReturnForUndefinedTypes":true}]
/**
* @returns {IterableIterator<any>}
*/
function * quux() {}
// Settings: {"jsdoc":{"mode":"typescript"}}
/**
* @returns {IterableIterator<any>}
*/
function * quux() {}
// Settings: {"jsdoc":{"mode":"jsdoc"}}
// "jsdoc/require-returns-check": ["error"|"warn", {"exemptGenerators":true}]
/**
* @param {unknown} val
* @returns { asserts val is number }
*/
function assertNumber(val) {
assert(typeof val === 'number');
}
/**
* Reads a test fixture.
*
* @param path The path to resolve relative to the fixture base. It will be normalized for the
* operating system.
*
* @returns The file contents as buffer.
*/
export function readFixture(path: string): Promise<Buffer>;
/**
* Reads a test fixture.
*
* @param path The path to resolve relative to the fixture base. It will be normalized for the
* operating system.
*
* @returns {SomeType} The file contents as buffer.
*/
export function readFixture(path: string): Promise<Buffer>;
/**
* Reads a test fixture.
*
* @param path The path to resolve relative to the fixture base. It will be normalized for the
* operating system.
*
* @returns The file contents as buffer.
*/
export function readFixture(path: string): Promise<Buffer> {
return new Promise(() => {});
}
/**
* Reads a test fixture.
*
* @param path The path to resolve relative to the fixture base. It will be normalized for the
* operating system.
*
* @returns {void} The file contents as buffer.
*/
export function readFixture(path: string);
/**
* @returns {SomeType}
*/
function quux (path) {
if (true) {
return 5;
}
return 15;
};
/**
* @returns {SomeType} Foo.
*/
const quux = () => new Promise((resolve) => {
resolve(3);
});
/**
* @returns {SomeType} Foo.
*/
const quux = function () {
return new Promise((resolve) => {
resolve(3);
});
};
/**
* @returns {true}
*/
function quux () {
if (true) {
return true;
}
throw new Error('Fail');
}
/**
* @returns Baz.
*/
function foo() {
switch (true) {
default:
switch (false) {
default: break;
}
return "baz";
}
};
/**
* Return a V1 style query identifier.
*
* @param {string} id - The query identifier.
* @returns {string} V1 style query identifier.
*/
function v1QueryId(id) {
switch (id) {
case 'addq':
case 'aliq':
case 'locq':
return id.substring(3);
case 'lost':
return id.substring(4);
default:
return id;
}
}
/**
* Parses the required header fields for the given SIP message.
*
* @param {string} logPrefix - The log prefix.
* @param {string} sipMessage - The SIP message.
* @param {string[]} headers - The header fields to be parsed.
* @returns {object} Object with parsed header fields.
*/
function parseSipHeaders(logPrefix, sipMessage, headers) {
try {
return esappSip.parseHeaders(sipMessage, headers);
} catch (err) {
logger.error(logPrefix, 'Failed to parse');
return {};
}
}
/**
* @returns {true}
*/
function quux () {
try {
} catch (error) {
} finally {
return true;
}
}
/** Returns true.
*
* @returns {boolean} true
*/
function getTrue() {
try {
return true;
} finally {
console.log('returning...');
}
}
/**
* Maybe return a boolean.
* @returns {boolean|void} true, or undefined.
*/
function maybeTrue() {
if (Math.random() > 0.5) {
return true;
}
}
/**
* @param {AST} astNode
* @returns {AST}
*/
const getTSFunctionComment = function (astNode) {
switch (greatGrandparent.type) {
case 'VariableDeclarator':
if (greatGreatGrandparent.type === 'VariableDeclaration') {
return greatGreatGrandparent;
}
default:
return astNode;
}
};
const f =
/**
* Description.
*
* @returns Result.
*/
() => {
return function () {};
};
/**
* Description.
*
* @returns Result.
*/
export function f(): string {
return "";
interface I {}
}
/**
* @param {boolean} bar A fun variable.
* @returns {*} Anything at all!
*/
function foo( bar ) {
if ( bar ) {
return functionWithUnknownReturnType();
}
}
/**
* @returns Baz.
*/
function foo() {
switch (true) {
default:
switch (false) {
default: return;
}
return "baz";
}
};
/**
* @returns
*/
const quux = (someVar) => {
if (someVar) {
return true;
}
};
/**
* @returns {number}
*/
function foo() {
while (true) {
const n = Math.random();
if (n < 0.5) {
return n;
}
}
}
/**
* @returns {number}
*/
function foo() {
for (;;) {
const n = Math.random();
if (n < 0.5) {
return n;
}
}
}