diff --git a/.README/README.md b/.README/README.md index 901642070..2df965948 100644 --- a/.README/README.md +++ b/.README/README.md @@ -361,6 +361,11 @@ how the keys of `preferredTypes` may have `<>` or `.<>` (or just `.`) appended and its bearing on whether types are checked as parents/children only (e.g., to match `Array` if the type is `Array` vs. `Array.`). +Note that if a value is present both as a key and as a value, neither the +key nor the value will be reported. Thus in `check-types`, this fact can +be used to allow both `object` and `Object` if one has a `preferredTypes` +key `object: 'Object'` and `Object: 'object'`. + ## Advanced ### AST and Selectors diff --git a/.README/rules/check-types.md b/.README/rules/check-types.md index 8c48b265c..97bac4472 100644 --- a/.README/rules/check-types.md +++ b/.README/rules/check-types.md @@ -55,6 +55,11 @@ RegExp `string[]` specifically as distinct from say `number[]`, but you can target both with `[]` or the child types `number` or `string`. +If a value is present both as a key and as a value, neither the key nor the +value will be reported. Thus one can use this fact to allow both `object` +and `Object`, for example. Note that in "typescript" mode, this is the default +behavior. + See also the documentation on `settings.jsdoc.preferredTypes` which impacts the behavior of `check-types`. diff --git a/README.md b/README.md index e10d6d0fe..257481950 100644 --- a/README.md +++ b/README.md @@ -423,6 +423,11 @@ how the keys of `preferredTypes` may have `<>` or `.<>` (or just `.`) appended and its bearing on whether types are checked as parents/children only (e.g., to match `Array` if the type is `Array` vs. `Array.`). +Note that if a value is present both as a key and as a value, neither the +key nor the value will be reported. Thus in `check-types`, this fact can +be used to allow both `object` and `Object` if one has a `preferredTypes` +key `object: 'Object'` and `Object: 'object'`. + ## Advanced @@ -3382,6 +3387,11 @@ RegExp `string[]` specifically as distinct from say `number[]`, but you can target both with `[]` or the child types `number` or `string`. +If a value is present both as a key and as a value, neither the key nor the +value will be reported. Thus one can use this fact to allow both `object` +and `Object`, for example. Note that in "typescript" mode, this is the default +behavior. + See also the documentation on `settings.jsdoc.preferredTypes` which impacts the behavior of `check-types`. @@ -3991,6 +4001,18 @@ function quux (foo) { } // Settings: {"jsdoc":{"preferredTypes":{"Array.<>":"[]","Array<>":"[]"}}} // Message: Invalid JSDoc @param "foo" type "Array"; prefer: "[]". + +/** + * @typedef {object} foo + */ +function a () {} + +/** + * @typedef {Object} foo + */ +function b () {} +// Settings: {"jsdoc":{"mode":"typescript","preferredTypes":{"object":"Object"}}} +// Message: Invalid JSDoc @typedef "foo" type "object"; prefer: "Object". ```` The following patterns are not considered problems: @@ -4224,6 +4246,37 @@ function quux () {} /** @typedef {object} foo */ // Settings: {"jsdoc":{"preferredTypes":{"object<>":"Object<>"}}} // Options: [{"exemptTagContexts":[{"tag":"typedef","types":["object"]}]}] + +/** + * @typedef {object} foo + */ + + /** + * @typedef {Object} foo + */ +// Settings: {"jsdoc":{"preferredTypes":{"object":"Object","Object":"object"}}} + +/** + * @typedef {object} foo + */ +function a () {} + +/** + * @typedef {Object} foo + */ +function b () {} +// Settings: {"jsdoc":{"preferredTypes":{"object":"Object","Object":"object"}}} + +/** + * @typedef {object} foo + */ +function a () {} + +/** + * @typedef {Object} foo + */ +function b () {} +// Settings: {"jsdoc":{"mode":"typescript"}} ```` diff --git a/src/rules/checkTypes.js b/src/rules/checkTypes.js index 3105a3e2a..fe78e01a2 100644 --- a/src/rules/checkTypes.js +++ b/src/rules/checkTypes.js @@ -115,7 +115,8 @@ export default iterateJsdoc(({ }); } } - const directNameMatch = preferredTypes?.[nodeName] !== undefined; + const directNameMatch = preferredTypes?.[nodeName] !== undefined && + !Object.values(preferredTypes).includes(nodeName); const unifiedSyntaxParentMatch = parentType && directNameMatch && unifyParentAndChildTypeChecks; isGenericMatch = isGenericMatch || unifiedSyntaxParentMatch; @@ -171,6 +172,9 @@ export default iterateJsdoc(({ } } else if (!noDefaults && type === 'NAME') { for (const strictNativeType of strictNativeTypes) { + if (strictNativeType === 'object' && mode === 'typescript') { + continue; + } if (strictNativeType.toLowerCase() === nodeName.toLowerCase() && strictNativeType !== nodeName && diff --git a/test/rules/assertions/checkTypes.js b/test/rules/assertions/checkTypes.js index a29fa6091..90475c97f 100644 --- a/test/rules/assertions/checkTypes.js +++ b/test/rules/assertions/checkTypes.js @@ -1924,6 +1924,44 @@ export default { }, }, }, + { + code: ` + /** + * @typedef {object} foo + */ + function a () {} + + /** + * @typedef {Object} foo + */ + function b () {} + `, + errors: [ + { + line: 3, + message: 'Invalid JSDoc @typedef "foo" type "object"; prefer: "Object".', + }, + ], + output: ` + /** + * @typedef {Object} foo + */ + function a () {} + + /** + * @typedef {Object} foo + */ + function b () {} + `, + settings: { + jsdoc: { + mode: 'typescript', + preferredTypes: { + object: 'Object', + }, + }, + }, + }, ], valid: [ { @@ -2387,5 +2425,63 @@ export default { }, }, }, + { + code: ` + /** + * @typedef {object} foo + */ + + /** + * @typedef {Object} foo + */ + `, + settings: { + jsdoc: { + preferredTypes: { + object: 'Object', + Object: 'object', + }, + }, + }, + }, + { + code: ` + /** + * @typedef {object} foo + */ + function a () {} + + /** + * @typedef {Object} foo + */ + function b () {} + `, + settings: { + jsdoc: { + preferredTypes: { + object: 'Object', + Object: 'object', + }, + }, + }, + }, + { + code: ` + /** + * @typedef {object} foo + */ + function a () {} + + /** + * @typedef {Object} foo + */ + function b () {} + `, + settings: { + jsdoc: { + mode: 'typescript', + }, + }, + }, ], };