Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no-undefined-types doesn't read local variables #178

Closed
cowwoc opened this issue Mar 21, 2019 · 12 comments · Fixed by #1363
Closed

no-undefined-types doesn't read local variables #178

cowwoc opened this issue Mar 21, 2019 · 12 comments · Fixed by #1363

Comments

@cowwoc
Copy link

cowwoc commented Mar 21, 2019

Given:

var ForwardDeclaration;

/**
 * Initializes the exported variables if they haven't been initialized before. See
 * <a href="https://stackoverflow.com/a/42704874/14731">Stackoverflow</a> for a related discussion.
 *
 * @return {undefined}
 */
function initExports()
{
	if (ForwardDeclaration)
		return;

	class TestClass
	{
		constructor(name)
		{
			// eslint-disable-next-line no-console
			console.log(name);
		}

		/**
		 * @param {TestClass} other another instance of {@code TestClass}
		 * @return {TestClass} this
		 */
		isEqualTo(other)
		{
			return this;
		}
	}

	ForwardDeclaration = TestClass;
}

initExports();

export {ForwardDeclaration as TestClass, initExports};

The plugin complains The type 'TestClass' is undefined. on line 23 (the @param). I am expecting a method to know about its enclosing class.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@ibbignerd
Copy link

Could not reproduce on v4.4.3 using the following settings. Might not be a bad idea to include your settings.

"rules": {
	"jsdoc/check-param-names": 2,
	"jsdoc/check-tag-names": 2,
	"jsdoc/require-hyphen-before-param-description": 2,
	"jsdoc/require-param": 2,
	"jsdoc/require-param-description": 2,
	"jsdoc/require-param-name": 2,
	"jsdoc/require-param-type": 2,
	"jsdoc/check-types": 2,
	"jsdoc/valid-types": 2,
	"jsdoc/require-returns-type": 2,
	"jsdoc/require-returns": 2,

	"jsdoc/require-returns-check": 1,
	"jsdoc/no-undefined-types": 1,

	"jsdoc/check-examples": 0,
	"jsdoc/require-example": 0,
	"jsdoc/require-description": 0,
	"jsdoc/require-description-complete-sentence": 0,
	"jsdoc/newline-after-description": 0,
	"jsdoc/require-returns-description": 0,
}

@gajus gajus added the question label Mar 26, 2019
@cowwoc
Copy link
Author

cowwoc commented Mar 27, 2019

Here you go:

{
  "extends": "eslint:recommended",
  "parserOptions": {
    "ecmaVersion": 2017,
    "sourceType": "module"
  },
  "plugins": [
    "jsdoc"
  ],
  "settings": {
    "jsdoc": {
      "tagNamePreference": {
        "returns": "return"
      }
    }
  },
  "rules": {
    "no-constant-condition": [
      "error",
      {
        "checkLoops": false
      }
    ],
    //    "valid-jsdoc": [
    //      "warn",
    //      {
    //        "prefer": {
    //          "returns": "return"
    //        },
    //        "preferType": {
    //          "object": "Object",
    //          "string": "String",
    //          "number": "Number"
    //        },
    //        "requireReturnType": true,
    //        "requireParamDescription": true,
    //        "requireReturnDescription": true
    //      }
    //    ],
    "block-scoped-var": "error",
    "consistent-return": [
      "error",
      {
        "treatUndefinedAsUnspecified": true
      }
    ],
    "dot-location": "error",
    "dot-notation": "error",
    "eqeqeq": "error",
    "no-caller": "error",
    "no-div-regex": "error",
    "no-else-return": "error",
    "no-empty-function": "error",
    "no-eq-null": "error",
    "no-eval": "error",
    "no-extend-native": "error",
    "no-extra-bind": "error",
    "no-extra-label": "error",
    "no-floating-decimal": "error",
    "no-global-assign": "error",
    "no-implicit-coercion": "error",
    "no-implicit-globals": "error",
    "no-implied-eval": "error",
    "no-invalid-this": "error",
    "no-iterator": "error",
    "no-lone-blocks": "error",
    "no-loop-func": "error",
    "no-magic-numbers": "off",
    "no-multi-spaces": "error",
    "no-multi-str": "error",
    "no-new-func": "error",
    "no-new-wrappers": "error",
    "no-new": "warn",
    "no-octal-escape": "error",
    "no-param-reassign": "off",
    "no-proto": "error",
    //"no-restricted-properties": "error",
    "no-return-assign": "error",
    //"no-return-await": "error",
    "no-script-url": "error",
    "no-self-compare": "error",
    "no-sequences": "error",
    "no-throw-literal": "error",
    "no-unmodified-loop-condition": "error",
    "no-unused-expressions": "error",
    "no-useless-call": "error",
    "no-useless-concat": "error",
    //"no-useless-return": "error",
    "no-void": "error",
    "no-with": "error",
    "radix": "error",
    //"require-await": "error",
    //"vars-on-top": "error", <-- needed by https://stackoverflow.com/a/42704874/14731
    "wrap-iife": "error",
    "yoda": "error",
    "strict": "error",
    "no-catch-shadow": "error",
    "no-label-var": "error",
    "no-restricted-globals": "error",
    "no-shadow-restricted-names": "error",
    "no-shadow": "error",
    "no-undef-init": "error",
    "no-undefined": "error",
    "no-use-before-define": [
      "error",
      {
        "functions": false
      }
    ],
    "callback-return": "error",
    "global-require": "error",
    "handle-callback-err": "error",
    "no-mixed-requires": "error",
    "no-new-require": "error",
    "no-path-concat": "error",
    "no-process-env": "error",
    "no-process-exit": "error",
    "no-restricted-modules": "error",
    "no-sync": "error",
    "array-bracket-spacing": "error",
    "block-spacing": "error",
    // Disabled until https://youtrack.jetbrains.com/issue/WEB-25425 is fixed
    //		"brace-style": [
    //			"error",
    //			"allman"
    //		],
    "camelcase": "error",
    //"capitalized-comments": "error",
    "comma-dangle": "error",
    "comma-spacing": "error",
    "comma-style": "error",
    "computed-property-spacing": "error",
    "consistent-this": "error",
    //"eol-last": [
    //	"error",
    //	"never"
    //],
    "func-call-spacing": "error",
    //"func-name-matching": "error",
    //"func-names": [
    //	"error",
    //	"as-needed"
    //],
    "func-style": [
      "error",
      "declaration"
    ],
    "id-blacklist": "error",
    "id-length": "off",
    "id-match": "error",
    "indent": [
      "error",
      "tab",
      {
        "SwitchCase": 1
      }
    ],
    "jsx-quotes": "error",
    "key-spacing": "error",
    "keyword-spacing": "error",
    //"line-comment-position": "error",
    "linebreak-style": "off",
    //"lines-around-comment": "error",
    //"lines-around-directive": "error",
    "max-depth": "error",
    "max-len": [
      "error",
      {
        "code": 120,
        "tabWidth": 2
      }
    ],
    "max-lines": "off",
    "max-nested-callbacks": "error",
    "max-params": [
      "warn",
      {
        "max": 7
      }
    ],
    "max-statements-per-line": "error",
    "max-statements": [
      "error",
      {
        "max": 25
      }
    ],
    "multiline-ternary": "error",
    "new-cap": "error",
    "new-parens": "error",
    "newline-after-var": "off",
    "newline-before-return": "off",
    "newline-per-chained-call": "off",
    "no-array-constructor": "error",
    "no-bitwise": "error",
    "no-continue": "off",
    "no-inline-comments": "error",
    "no-lonely-if": "error",
    "no-mixed-operators": "error",
    "no-mixed-spaces-and-tabs": "error",
    "no-multiple-empty-lines": "error",
    "no-negated-condition": "error",
    "no-nested-ternary": "error",
    "no-new-object": "error",
    "no-plusplus": "off",
    "no-restricted-syntax": "error",
    "no-tabs": "off",
    "no-ternary": "error",
    "no-trailing-spaces": "error",
    "no-underscore-dangle": "error",
    "no-unneeded-ternary": "error",
    "no-whitespace-before-property": "error",
    "object-curly-newline": "off",
    "object-curly-spacing": "error",
    "object-property-newline": "error",
    "one-var-declaration-per-line": "error",
    "one-var": [
      "error",
      "never"
    ],
    "operator-assignment": "error",
    "operator-linebreak": "error",
    "padded-blocks": [
      "error",
      {
        "blocks": "never",
        "classes": "never",
        "switches": "never"
      }
    ],
    "quote-props": [
      "error",
      "as-needed"
    ],
    "quotes": "error",
    //    "require-jsdoc": "error",
    "semi-spacing": "error",
    "semi": "error",
    "sort-keys": "off",
    "sort-vars": "error",
    "space-before-blocks": "error",
    "space-before-function-paren": "off",
    "space-in-parens": "error",
    "space-infix-ops": "error",
    "spaced-comment": "off",
    "unicode-bom": "error",
    "wrap-regex": "error",
    "arrow-body-style": "error",
    "arrow-parens": [
      "error",
      "as-needed"
    ],
    "arrow-spacing": "error",
    "generator-star-spacing": "error",
    "no-confusing-arrow": "error",
    "no-duplicate-imports": "error",
    "no-restricted-imports": "error",
    "no-useless-computed-key": "error",
    "no-useless-constructor": "error",
    "no-useless-rename": "error",
    // "no-var": "error", <-- needed by https://stackoverflow.com/a/42704874/14731
    "object-shorthand": "error",
    "prefer-arrow-callback": "off",
    "prefer-const": [
      "error",
      {
        "ignoreReadBeforeAssign": true
      }
    ],
    //"prefer-destructuring": "error",
    //"prefer-numeric-literals": "error",
    "prefer-rest-params": "error",
    "prefer-spread": "error",
    "prefer-template": "off",
    "rest-spread-spacing": "error",
    //"sort-imports": [
    //  "error",
    //  {
    //    "ignoreCase": true
    //  }
    //],
    "symbol-description": "error",
    "template-curly-spacing": "error",
    "yield-star-spacing": "error",
    "jsdoc/check-examples": "error",
    "jsdoc/check-param-names": "error",
    "jsdoc/check-tag-names": "error",
    "jsdoc/check-types": "error",
    "jsdoc/newline-after-description": "error",
    "jsdoc/no-undefined-types": "error",
    "jsdoc/require-description": "off",
    "jsdoc/require-description-complete-sentence": "off",
    "jsdoc/require-example": "off",
    "jsdoc/require-hyphen-before-param-description": "off",
    "jsdoc/require-param": "error",
    "jsdoc/require-param-description": "error",
    "jsdoc/require-param-name": "error",
    "jsdoc/require-param-type": "error",
    "jsdoc/require-returns": "error",
    "jsdoc/require-returns-check": "error",
    "jsdoc/require-returns-description": "error",
    "jsdoc/require-returns-type": "error",
    "jsdoc/valid-types": "error"
  }
}

You might have to uncomment some of the rules to trigger this issue. I forget. I worked around this issue by changing the way I was handling circular dependencies (https://stackoverflow.com/a/42264822/14731). Thanks.

@brettz9
Copy link
Collaborator

brettz9 commented May 17, 2019

Reducing the config file to the following simplified test case replicates as well:

module.exports = {
  "parserOptions": {
    "ecmaVersion": 2017,
    "sourceType": "module"
  },
  "plugins": [
    "jsdoc"
  ],
  "rules": {
    "jsdoc/no-undefined-types": "error"
  }
};

@brettz9
Copy link
Collaborator

brettz9 commented May 17, 2019

And yes, the current behavior indeed only checks globals (or, in the case of modules, the module scope).

@brettz9 brettz9 changed the title no-undefined-types complains about classes declared by functions no-undefined-types doesn't read local variables May 17, 2019
@brettz9
Copy link
Collaborator

brettz9 commented May 28, 2023

With #1098 now dropping jsdoc/no-undefined-types from the recommended rules for typescript configs (including a new config recommended-typescript-flavor for plain JavaScript), and with TypeScript handling this properly, I think we can drop this. We can accept PRs if anyone can fix this for non-TypeScript modes, but I don't think this should be a priority with TypeScript now being the default mode.

@sebastian-fredriksson-bernholtz
Copy link
Contributor

@brettz9 Sorry, I can't figure out how to get typescript to flag invalid references in jsdoc. I've checked tsconfig docs, but can't find anything about checking references in jsdoc. How do you get typescript to check that types in jsdoc comments are defined instead of using this rule?

@brettz9
Copy link
Collaborator

brettz9 commented Mar 14, 2025

@brettz9 Sorry, I can't figure out how to get typescript to flag invalid references in jsdoc. I've checked tsconfig docs, but can't find anything about checking references in jsdoc. How do you get typescript to check that types in jsdoc comments are defined instead of using this rule?

Have you tried compilerOptions -> checkJs (along with compilerOptions -> allowJs)?

@sebastian-fredriksson-bernholtz
Copy link
Contributor

@brettz9 All my code is typescript, hence typechecked by tsc, so I had not. I added it just in case it's required to trigger typechecking of jsdoc in ts files, but typescript is still not reporting any issues:

Image

Note that the only issue on l.430 is the eslint issue but typescript issues are detected in the file (l.431). Typescript considers the type to be any because it doesn't know what it is. Typescript version is slightly old 5.6.3, but changing to 5.8.2 gives same result. No issue is reported when running from cli either.

Do you have any references to typescript reporting invalid references in jsdoc, and how to activate it? My google-fu might be failing me but I struggle to find anything about it. Everything I come across - including Github Copilot - says that typescript doesn't do it and suggests using this eslint rule.

Image

@brettz9
Copy link
Collaborator

brettz9 commented Mar 15, 2025

Does your include allow for .js files? You can look at this repository for how we do it...

@sebastian-fredriksson-bernholtz
Copy link
Contributor

sebastian-fredriksson-bernholtz commented Mar 15, 2025

Does your include allow for .js files? You can look at this repository for how we do it...

@brettz9 It does, but I have no .js files. However, since you kept referring to js files, I decided to try a js file instead and found that while my example isn't reported by typechecking in js files, other things are. They are just not reported in ts files:

  • Typescript will report error for unresolved type reference for a @param in js files only, not in ts files!
    noImplicitAny will still catch it though, as will using typescript syntax rather than jsdoc syntax, so no big deal.
  • Typescript will not report error for @link in either ts nor js files!
    ⛔️ This means that this rule still provides a functionality that typescript does not, whether you use js or ts.
Image

@brettz9
Copy link
Collaborator

brettz9 commented Mar 16, 2025

@brettz9 It does, but I have no .js files. However, since you kept referring to js files

My apologies. I was hoping to expedite things despite not having time then to read your message carefully.

I decided to try a js file instead and found that while my example isn't reported by typechecking in js files, other things are. They are just not reported in ts files:

* Typescript will report error for unresolved type reference for a `@param` in `js` files only, **NOT** in `ts` files!

Yes, for this reason, TypeScript users tend to put their types as TypeScript and then use the jsdoc/no-types rule (through one of the typescript configs) to prevent use of types within JSDoc, so that is not an issue for them.

  `noImplicitAny` will still catch it though, as will using **typescript** syntax rather than **jsdoc** syntax, so no big deal.

* Typescript will **not** report error for `@link` in either `ts` nor `js` files!
  ⛔️ This means that this plugin still provides a functionality that typescript does not, whether you use `js` or `ts`.

For a variety of reasons, it is difficult to maintain the no-undefined-types rule to be fully aware of its environment. If you want to add a PR that supports the desired features, we will hopefully be able to review, but we are not actively developing it ourselves.

Copy link

🎉 This issue has been resolved in version 50.6.7 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants