Functions in TypeScript often don't need to be given an explicit return type annotation.
Leaving off the return type is less code to read or write and allows the compiler to infer it from the contents of the function.
However, explicit return types do make it visually more clear what type is returned by a function.
They can also speed up TypeScript type checking performance in large codebases with many large functions.
This rule enforces that functions do have an explicit return type annotation.
.eslintrc.cjs
module.exports = {
"rules": {
"@typescript-eslint/explicit-function-return-type": "error"
}
};
Try this rule in the playground ↗
Examples
function test() {
return;
}
var fn = function () {
return 1;
};
var arrowFn = () => 'test';
class Test {
method() {
return;
}
}
Open in Playground
function test(): void {
return;
}
var fn = function (): number {
return 1;
};
var arrowFn = (): string => 'test';
class Test {
method(): void {
return;
}
}
Open in Playground
Options
This rule accepts the following options:
type Options = [
{
allowConciseArrowFunctionExpressionsStartingWithVoid?: boolean;
allowDirectConstAssertionInArrowFunctions?: boolean;
allowExpressions?: boolean;
allowFunctionsWithoutTypeParameters?: boolean;
allowHigherOrderFunctions?: boolean;
allowIIFEs?: boolean;
allowTypedFunctionExpressions?: boolean;
allowedNames?: string[];
},
];
const defaultOptions: Options = [
{
allowExpressions: false,
allowTypedFunctionExpressions: true,
allowHigherOrderFunctions: true,
allowDirectConstAssertionInArrowFunctions: true,
allowConciseArrowFunctionExpressionsStartingWithVoid: false,
allowFunctionsWithoutTypeParameters: false,
allowedNames: [],
allowIIFEs: false,
},
];
Configuring in a mixed JS/TS codebase
If you are working on a codebase within which you lint non-TypeScript code (i.e.
.js
/
.mjs
/
.cjs
/
.jsx
), you should ensure that you should use
ESLint
overrides
to only enable the rule on
.ts
/
.mts
/
.cts
/
.tsx
files. If you don't, then you will get unfixable lint errors reported within
.js
/
.mjs
/
.cjs
/
.jsx
files.
{
"rules": {
// disable the rule for all files
"@typescript-eslint/explicit-function-return-type": "off",
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-function-return-type": "error",
},
},
],
}
allowExpressions
Examples of code for this rule with
{ allowExpressions: true }
:
node.addEventListener('click', () => {});
node.addEventListener('click', function () {});
const foo = arr.map(i => i * i);
Open in Playground
allowTypedFunctionExpressions
Examples of code for this rule with
{ allowTypedFunctionExpressions: true }
:
let arrowFn = () => 'test';
let funcExpr = function () {
return 'test';
};
let objectProp = {
foo: () => 1,
};
Open in Playground
type FuncType = () => string;
let arrowFn: FuncType = () => 'test';
let funcExpr: FuncType = function () {
return 'test';
};
let asTyped = (() => '') as () => string;
let castTyped = <() => string>(() => '');
interface ObjectType {
foo(): number;
}
let objectProp: ObjectType = {
foo: () => 1,
};
let objectPropAs = {
foo: () => 1,
} as ObjectType;
let objectPropCast = <ObjectType>{
foo: () => 1,
};
declare function functionWithArg(arg: () => number);
functionWithArg(() => 1);
declare function functionWithObjectArg(arg: { method: () => number });
functionWithObjectArg({
method() {
return 1;
},
});
Open in Playground
allowHigherOrderFunctions
Examples of code for this rule with
{ allowHigherOrderFunctions: true }
:
var arrowFn = () => (): void => {};
function fn() {
return function (): void {};
}
Open in Playground
allowDirectConstAssertionInArrowFunctions
Examples of code for this rule with
{ allowDirectConstAssertionInArrowFunctions: true }
:
const func = (value: number) => ({ type: 'X', value }) as any;
const func = (value: number) => ({ type: 'X', value }) as Action;
Open in Playground
const func = (value: number) => ({ foo: 'bar', value }) as const;
const func = () => x as const;
Open in Playground
allowConciseArrowFunctionExpressionsStartingWithVoid
Examples of code for this rule with
{ allowConciseArrowFunctionExpressionsStartingWithVoid: true }
:
var join = (a: string, b: string) => `${a}${b}`;
const log = (message: string) => {
console.log(message);
};
Open in Playground
allowFunctionsWithoutTypeParameters
Examples of code for this rule with
{ allowFunctionsWithoutTypeParameters: true }
:
function foo<T>(t: T): T {
return t;
}
const bar = <T>(t: T): T => t;
function allowedFunction(x: string) {
return x;
}
const allowedArrow = (x: string) => x;
Open in Playground
allowedNames
You may pass function/method names you would like this rule to ignore, like so:
{
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowedNames": ["ignoredFunctionName", "ignoredMethodName"]
}
]
}
allowIIFEs
Examples of code for this rule with
{ allowIIFEs: true }
:
When Not To Use It
If you don't find the added cost of explicitly writing function return types to be worth the visual clarity, or your project is not large enough for it to be a factor in type checking performance, then you will not need this rule.
Further Reading
TypeScript
Functions
Resources