diff --git a/.README/rules/require-param.md b/.README/rules/require-param.md
index 978f055c2..db665383c 100644
--- a/.README/rules/require-param.md
+++ b/.README/rules/require-param.md
@@ -374,6 +374,15 @@ supplied as default values. Defaults to `false`.
Set to `true` to ignore reporting when all params are missing. Defaults to
`false`.
+### `interfaceExemptsParamsCheck`
+
+Set if you wish TypeScript interfaces to exempt checks for the existence of
+`@param`'s.
+
+Will check for a type defining the function itself (on a variable
+declaration) or if there is a single destructured object with a type.
+Defaults to `false`.
+
## Context and settings
| | |
@@ -382,7 +391,7 @@ Set to `true` to ignore reporting when all params are missing. Defaults to
| Tags | `param` |
| Aliases | `arg`, `argument` |
|Recommended | true|
-| Options |`autoIncrementBase`, `checkConstructors`, `checkDestructured`, `checkDestructuredRoots`, `checkGetters`, `checkRestProperty`, `checkSetters`, `checkTypesPattern`, `contexts`, `enableFixer`, `enableRestElementFixer`, `enableRootFixer`, `exemptedBy`, `ignoreWhenAllParamsMissing`, `unnamedRootBase`, `useDefaultObjectProperties`|
+| Options |`autoIncrementBase`, `checkConstructors`, `checkDestructured`, `checkDestructuredRoots`, `checkGetters`, `checkRestProperty`, `checkSetters`, `checkTypesPattern`, `contexts`, `enableFixer`, `enableRestElementFixer`, `enableRootFixer`, `exemptedBy`, `ignoreWhenAllParamsMissing`, `interfaceExemptsParamsCheck`, `unnamedRootBase`, `useDefaultObjectProperties`|
| Settings | `ignoreReplacesDocs`, `overrideReplacesDocs`, `augmentsExtendsReplacesDocs`, `implementsReplacesDocs`|
## Failing examples
diff --git a/docs/rules/require-param.md b/docs/rules/require-param.md
index 281c7190c..0dc07fd70 100644
--- a/docs/rules/require-param.md
+++ b/docs/rules/require-param.md
@@ -24,6 +24,7 @@
* [`checkDestructuredRoots`](#user-content-require-param-options-checkdestructuredroots)
* [`useDefaultObjectProperties`](#user-content-require-param-options-usedefaultobjectproperties)
* [`ignoreWhenAllParamsMissing`](#user-content-require-param-options-ignorewhenallparamsmissing)
+ * [`interfaceExemptsParamsCheck`](#user-content-require-param-options-interfaceexemptsparamscheck)
* [Context and settings](#user-content-require-param-context-and-settings)
* [Failing examples](#user-content-require-param-failing-examples)
* [Passing examples](#user-content-require-param-passing-examples)
@@ -445,6 +446,17 @@ supplied as default values. Defaults to `false`.
Set to `true` to ignore reporting when all params are missing. Defaults to
`false`.
+
+
+### interfaceExemptsParamsCheck
+
+Set if you wish TypeScript interfaces to exempt checks for the existence of
+`@param`'s.
+
+Will check for a type defining the function itself (on a variable
+declaration) or if there is a single destructured object with a type.
+Defaults to `false`.
+
## Context and settings
@@ -455,7 +467,7 @@ Set to `true` to ignore reporting when all params are missing. Defaults to
| Tags | `param` |
| Aliases | `arg`, `argument` |
|Recommended | true|
-| Options |`autoIncrementBase`, `checkConstructors`, `checkDestructured`, `checkDestructuredRoots`, `checkGetters`, `checkRestProperty`, `checkSetters`, `checkTypesPattern`, `contexts`, `enableFixer`, `enableRestElementFixer`, `enableRootFixer`, `exemptedBy`, `ignoreWhenAllParamsMissing`, `unnamedRootBase`, `useDefaultObjectProperties`|
+| Options |`autoIncrementBase`, `checkConstructors`, `checkDestructured`, `checkDestructuredRoots`, `checkGetters`, `checkRestProperty`, `checkSetters`, `checkTypesPattern`, `contexts`, `enableFixer`, `enableRestElementFixer`, `enableRootFixer`, `exemptedBy`, `ignoreWhenAllParamsMissing`, `interfaceExemptsParamsCheck`, `unnamedRootBase`, `useDefaultObjectProperties`|
| Settings | `ignoreReplacesDocs`, `overrideReplacesDocs`, `augmentsExtendsReplacesDocs`, `implementsReplacesDocs`|
@@ -1185,6 +1197,25 @@ function quux (a, b) {}
export type Test = (foo: number) => string;
// "jsdoc/require-param": ["error"|"warn", {"contexts":["TSFunctionType"]}]
// Message: Missing JSDoc @param "foo" declaration.
+
+/**
+ *
+ */
+const quux = function quux (foo) {
+};
+// "jsdoc/require-param": ["error"|"warn", {"interfaceExemptsParamsCheck":true}]
+// Message: Missing JSDoc @param "foo" declaration.
+
+/**
+ *
+ */
+function quux ({
+ abc,
+ def
+}) {
+}
+// "jsdoc/require-param": ["error"|"warn", {"interfaceExemptsParamsCheck":true}]
+// Message: Missing JSDoc @param "root0" declaration.
````
@@ -1853,5 +1884,22 @@ function myFunction(foo: string): void;
*/
function myFunction(): void;
function myFunction(foo?: string) {}
+
+/**
+ *
+ */
+const quux: FunctionInterface = function quux (foo) {
+};
+// "jsdoc/require-param": ["error"|"warn", {"interfaceExemptsParamsCheck":true}]
+
+/**
+ *
+ */
+function quux ({
+ abc,
+ def
+}: FunctionInterface) {
+}
+// "jsdoc/require-param": ["error"|"warn", {"interfaceExemptsParamsCheck":true}]
````
diff --git a/src/rules.d.ts b/src/rules.d.ts
index 2b9b822fe..53f21ec79 100644
--- a/src/rules.d.ts
+++ b/src/rules.d.ts
@@ -591,6 +591,7 @@ export interface Rules {
enableRootFixer?: boolean;
exemptedBy?: string[];
ignoreWhenAllParamsMissing?: boolean;
+ interfaceExemptsParamsCheck?: boolean;
unnamedRootBase?: string[];
useDefaultObjectProperties?: boolean;
}
diff --git a/src/rules/requireParam.js b/src/rules/requireParam.js
index c3f0bcc68..ed0294dcb 100644
--- a/src/rules/requireParam.js
+++ b/src/rules/requireParam.js
@@ -35,6 +35,7 @@ const rootNamer = (desiredRoots, currentIndex) => {
export default iterateJsdoc(({
context,
jsdoc,
+ node,
utils,
}) => {
/* eslint-enable complexity -- Temporary */
@@ -57,12 +58,28 @@ export default iterateJsdoc(({
enableRestElementFixer = true,
enableRootFixer = true,
ignoreWhenAllParamsMissing = false,
+ interfaceExemptsParamsCheck = false,
unnamedRootBase = [
'root',
],
useDefaultObjectProperties = false,
} = context.options[0] || {};
+ if (interfaceExemptsParamsCheck) {
+ if (node && 'params' in node && node.params.length === 1 &&
+ node.params?.[0] && typeof node.params[0] === 'object' &&
+ node.params[0].type === 'ObjectPattern' &&
+ 'typeAnnotation' in node.params[0] && node.params[0].typeAnnotation
+ ) {
+ return;
+ }
+
+ if (node && node.parent.type === 'VariableDeclarator' &&
+ 'typeAnnotation' in node.parent.id && node.parent.id.typeAnnotation) {
+ return;
+ }
+ }
+
const preferredTagName = /** @type {string} */ (utils.getPreferredTagName({
tagName: 'param',
}));
@@ -579,6 +596,9 @@ export default iterateJsdoc(({
ignoreWhenAllParamsMissing: {
type: 'boolean',
},
+ interfaceExemptsParamsCheck: {
+ type: 'boolean',
+ },
unnamedRootBase: {
items: {
type: 'string',
diff --git a/test/rules/assertions/requireParam.js b/test/rules/assertions/requireParam.js
index 5d4d13d57..11296fb89 100644
--- a/test/rules/assertions/requireParam.js
+++ b/test/rules/assertions/requireParam.js
@@ -2587,6 +2587,87 @@ export default /** @type {import('../index.js').TestCases} */ ({
export type Test = (foo: number) => string;
`,
},
+ {
+ code: `
+ /**
+ *
+ */
+ const quux = function quux (foo) {
+ };
+ `,
+ errors: [
+ {
+ line: 2,
+ message: 'Missing JSDoc @param "foo" declaration.',
+ },
+ ],
+ languageOptions: {
+ parser: typescriptEslintParser,
+ sourceType: 'module',
+ },
+ options: [
+ {
+ interfaceExemptsParamsCheck: true,
+ },
+ ],
+ output: `
+ /**
+ *
+ * @param foo
+ */
+ const quux = function quux (foo) {
+ };
+ `,
+ },
+
+ {
+ code: `
+ /**
+ *
+ */
+ function quux ({
+ abc,
+ def
+ }) {
+ }
+ `,
+ errors: [
+ {
+ line: 2,
+ message: 'Missing JSDoc @param "root0" declaration.',
+ },
+ {
+ line: 2,
+ message: 'Missing JSDoc @param "root0.abc" declaration.',
+ },
+ {
+ line: 2,
+ message: 'Missing JSDoc @param "root0.def" declaration.',
+ },
+ ],
+ languageOptions: {
+ parser: typescriptEslintParser,
+ sourceType: 'module',
+ },
+ options: [
+ {
+ interfaceExemptsParamsCheck: true,
+ },
+ ],
+ output: `
+ /**
+ *
+ * @param root0
+ * @param root0.abc
+ * @param root0.def
+ */
+ function quux ({
+ abc,
+ def
+ }) {
+ }
+ `,
+ },
],
valid: [
{
@@ -3695,5 +3776,45 @@ export default /** @type {import('../index.js').TestCases} */ ({
sourceType: 'module',
},
},
+ {
+ code: `
+ /**
+ *
+ */
+ const quux: FunctionInterface = function quux (foo) {
+ };
+ `,
+ languageOptions: {
+ parser: typescriptEslintParser,
+ sourceType: 'module',
+ },
+ options: [
+ {
+ interfaceExemptsParamsCheck: true,
+ },
+ ],
+ },
+
+ {
+ code: `
+ /**
+ *
+ */
+ function quux ({
+ abc,
+ def
+ }: FunctionInterface) {
+ }
+ `,
+ languageOptions: {
+ parser: typescriptEslintParser,
+ sourceType: 'module',
+ },
+ options: [
+ {
+ interfaceExemptsParamsCheck: true,
+ },
+ ],
+ },
],
});