Skip to main content

explicit-module-boundary-types

Require explicit return and argument types on exported functions' and classes' public class methods.

Explicit types for function return values and arguments makes it clear to any calling code what is the module boundary's input and output. Adding explicit type annotations for those types can help improve code readability. It can also improve TypeScript type checking performance on larger codebases.

.eslintrc.cjs
module.exports = {
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "error"
}
};
Try this rule in the playground ↗

Examples

// Should indicate that no value is returned (void)
export function test() {
return;
}

// Should indicate that a number is returned
export default function () {
return 1;
}

// Should indicate that a string is returned
export var arrowFn = () => 'test';

// All arguments should be typed
export var arrowFn = (arg): string => `test ${arg}`;
export var arrowFn = (arg: any): string => `test ${arg}`;

export class Test {
// Should indicate that no value is returned (void)
method() {
return;
}
}

This rule accepts an options object with the following properties:

interface Options {
/**
* Whether to ignore arguments that are explicitly typed as `any`.
*/
allowArgumentsExplicitlyTypedAsAny?: boolean;
/**
* Whether to ignore return type annotations on body-less arrow functions that return an `as const` type assertion.
* You must still type the parameters of the function.
*/
allowDirectConstAssertionInArrowFunctions?: boolean;
/**
* An array of function/method names that will not have their arguments or return values checked.
*/
allowedNames?: string[];
/**
* Whether to ignore return type annotations on functions immediately returning another function expression.
* You must still type the parameters of the function.
*/
allowHigherOrderFunctions?: boolean;
/**
* Whether to ignore type annotations on the variable of a function expresion.
*/
allowTypedFunctionExpressions?: boolean;
shouldTrackReferences?: boolean;
}

const defaultOptions: Options = [
{
allowArgumentsExplicitlyTypedAsAny: false,
allowDirectConstAssertionInArrowFunctions: true,
allowedNames: [],
allowHigherOrderFunctions: true,
allowTypedFunctionExpressions: true,
},
];

Options

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-module-boundary-types": "off"
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "error"
}
}
]
}

allowArgumentsExplicitlyTypedAsAny

Examples of code for this rule with { allowArgumentsExplicitlyTypedAsAny: false }:

export const func = (value: any): number => value + 1;

allowDirectConstAssertionInArrowFunctions

Examples of code for this rule with { allowDirectConstAssertionInArrowFunctions: false }:

export const func = (value: number) => ({ type: 'X', value });
export const foo = () => ({
bar: true,
});
export const bar = () => 1;

allowedNames

You may pass function/method names you would like this rule to ignore, like so:

{
"@typescript-eslint/explicit-module-boundary-types": [
"error",
{
"allowedNames": ["ignoredFunctionName", "ignoredMethodName"]
}
]
}

allowHigherOrderFunctions

Examples of code for this rule with { allowHigherOrderFunctions: false }:

export const arrowFn = () => () => {};

export function fn() {
return function () {};
}

export function foo(outer: string) {
return function (inner: string) {};
}

allowTypedFunctionExpressions

Examples of code for this rule with { allowTypedFunctionExpressions: false }:

export let arrowFn = () => 'test';

export let funcExpr = function () {
return 'test';
};

export let objectProp = {
foo: () => 1,
};

export const foo = bar => {};

When Not To Use It

If you wish to make sure all functions have explicit return types, as opposed to only the module boundaries, you can use explicit-function-return-type

Further Reading

Resources