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.
- Flat Config
- Legacy Config
export default tseslint.config({
rules: {
"@typescript-eslint/explicit-module-boundary-types": "error"
}
});
module.exports = {
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "error"
}
};
Try this rule in the playground ↗
Examples
- ❌ Incorrect
- ✅ Correct
// Should indicate that no value is returned (void)
export function test() {
return;
}
// 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;
}
}
Open in Playground// A function with no return value (void)
export function test(): void {
return;
}
// A return value of type string
export var arrowFn = (): string => 'test';
// All arguments should be typed
export var arrowFn = (arg: string): string => `test ${arg}`;
export var arrowFn = (arg: unknown): string => `test ${arg}`;
export class Test {
// A class method with no return value (void)
method(): void {
return;
}
}
// The function does not apply because it is not an exported function.
function test() {
return;
}
Open in PlaygroundOptions
This rule accepts the following options:
type 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;
/**
* 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 expression. */
allowTypedFunctionExpressions?: boolean;
/** An array of function/method names that will not have their arguments or return values checked. */
allowedNames?: string[];
},
];
const defaultOptions: Options = [
{
allowArgumentsExplicitlyTypedAsAny: false,
allowDirectConstAssertionInArrowFunctions: true,
allowedNames: [],
allowHigherOrderFunctions: true,
allowTypedFunctionExpressions: true,
},
];
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
Whether to ignore arguments that are explicitly typed as any
. Default: false
.
Examples of code for this rule with { allowArgumentsExplicitlyTypedAsAny: false }
:
- ❌ Incorrect
- ✅ Correct
export const func = (value: any): number => value + 1;
Open in Playgroundexport const func = (value: any): number => value + 1;
Open in PlaygroundallowDirectConstAssertionInArrowFunctions
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. Default: true
.
Examples of code for this rule with { allowDirectConstAssertionInArrowFunctions: false }
:
- ❌ Incorrect
- ✅ Correct
export const func = (value: number) => ({ type: 'X', value });
export const foo = () => ({
bar: true,
});
export const bar = () => 1;
Open in Playgroundexport const func = (value: number) => ({ type: 'X', value }) as const;
export const foo = () =>
({
bar: true,
}) as const;
export const bar = () => 1 as const;
Open in PlaygroundallowedNames
An array of function/method names that will not have their arguments or return values checked. Default: []
.
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
Whether to ignore return type annotations on functions immediately returning another function expression.
You must still type the parameters of the function. Default: true
.
Examples of code for this rule with { allowHigherOrderFunctions: false }
:
- ❌ Incorrect
- ✅ Correct
export const arrowFn = () => () => {};
export function fn() {
return function () {};
}
export function foo(outer: string) {
return function (inner: string) {};
}
Open in Playgroundexport const arrowFn = () => (): void => {};
export function fn() {
return function (): void {};
}
export function foo(outer: string) {
return function (inner: string): void {};
}
Open in PlaygroundallowTypedFunctionExpressions
Whether to ignore type annotations on the variable of a function expression. Default: true
.
Examples of code for this rule with { allowTypedFunctionExpressions: false }
:
- ❌ Incorrect
- ✅ Correct
export let arrowFn = () => 'test';
export let funcExpr = function () {
return 'test';
};
export let objectProp = {
foo: () => 1,
};
export const foo = bar => {};
Open in Playgroundtype FuncType = () => string;
export let arrowFn: FuncType = () => 'test';
export let funcExpr: FuncType = function () {
return 'test';
};
export let asTyped = (() => '') as () => string;
export let castTyped = <() => string>(() => '');
interface ObjectType {
foo(): number;
}
export let objectProp: ObjectType = {
foo: () => 1,
};
export let objectPropAs = {
foo: () => 1,
} as ObjectType;
export let objectPropCast = <ObjectType>{
foo: () => 1,
};
type FooType = (bar: string) => void;
export const foo: FooType = bar => {};
Open in PlaygroundWhen Not To Use It
If your project is not used by downstream consumers that are sensitive to API types, you can disable this rule.
Further Reading
- TypeScript Functions