gajus / eslint-plugin-jsdoc

JSDoc specific linting rules for ESLint.
Other
1.09k stars 157 forks source link

@types/eslint-plugin-jsdoc or bundle .d.ts #1130

Closed snebjorn closed 8 months ago

snebjorn commented 1 year ago

Motivation

With the new ESLint flat config we import plugins

import jsdoc from "eslint-plugin-jsdoc";

However that causes typescript in the VSCode to report an error due to missing type definitions.

Could not find a declaration file for module 'eslint-plugin-jsdoc'. 'myrepo/node_modules/eslint-plugin-jsdoc/dist/index.js' implicitly has an 'any' type. Try npm i --save-dev @types/eslint-plugin-jsdoc if it exists or add a new declaration (.d.ts) file containing declare module 'eslint-plugin-jsdoc';

Current behavior

There are no types for eslint-plugin-jsdoc

Desired behavior

eslint-plugin-jsdoc should bundle the typescript types.

I'm not sure this is correct, but here's an example of the d.ts

import type { ESLint } from "eslint";

interface JSDoc extends ESLint.Plugin {
  configs: ESLint.Plugin["configs"] & {
    recommended: ESLint.ConfigData;
    ["recommended-error"]: ESLint.ConfigData;
    ["recommended-typescript"]: ESLint.ConfigData;
    ["recommended-typescript-error"]: ESLint.ConfigData;
    ["recommended-typescript-flavor"]: ESLint.ConfigData;
    ["recommended-typescript-flavor-error"]: ESLint.ConfigData;
  };
}

export default JSDoc;

Alternatives considered

A DefinitelyTyped package @types/eslint-plugin-jsdoc

snebjorn commented 11 months ago

1139 added

https://github.com/gajus/eslint-plugin-jsdoc/blob/e8b14756c573bc7f6eb824f2e87b67bbd6a50fab/package.json#L86 but index.d.ts is missing from the distributed package

image

paulshryock commented 11 months ago

but index.d.ts is missing from the distributed package

That's because *.d.ts is explicitly ignored in .npmignore.

Looks like .npmignore should be updated to to not ignore index.d.ts.

brettz9 commented 11 months ago

Yes, sorry, I inadvertently actually added that when merely considering adding it.

I'm afraid that with some projects rather conscious about package size, that the multiple generated files may become cumbersome for some.

We could submit this to DefinitelyTyped, as you say, using what we're already able to generate.

snebjorn commented 11 months ago

I don't understand why package size matters for a dev dependency - unless it's ridiculously large πŸ˜ƒ

How big are the types? For comparison @typescript-eslint's types are 7 KB including .d.ts.map and 3.66 KB without. I'm not counting the AST types, as it doesn't seem relevant to using the package for linting.

Anyway, types bundled in the package is optimal but publishing a separate types package or via DefinitelyTyped also works πŸ“¦

brettz9 commented 11 months ago

For our project, it's 76 KB / 49 KB (with and without map files).

I am also unclear on why it should matter (IDEs which rely on linting tools perhaps?), but it really apparently does given how much attention projects have given us to package size (#1141 being only the most recent). I'm not keen to garner complaints on this (especially when typing is not really so critical for ESLint config files, beyond suppressing complaints in IDEs) and then having to yank the new typing feature from those who do want it.

While there are some who consider it an anti-pattern to publish within the package due to semver noise, I personally prefer it myself (projects ideally shouldn't need to track transitive dependencies themselves), but feel it is unfortunately necessary at this point.

what1s1ove commented 8 months ago

Hey guys!

Since Eslint 9 is on the horizon, I think it's essential to pay more attention to this issue and start preparing for the changes πŸ™

image
brettz9 commented 8 months ago

I've submitted #1180 which should do the trick. It appears that it will be sufficient and feasible to only publish the index file types.

what1s1ove commented 8 months ago

I've submitted #1180 which should do the trick. It appears that it will be sufficient and feasible to only publish the index file types.

Thank you so much!

github-actions[bot] commented 8 months ago

:tada: This issue has been resolved in version 47.0.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

brettz9 commented 8 months ago

If someone wouldn't mind letting us how it goes...

what1s1ove commented 8 months ago

If someone wouldn't mind letting us how it goes...

This is definitely better, but still requires type casting, as index signature is used.

image

Here is the final result:

image

Perhaps you would like to make the keys (configs' names) explicit, as is done in the native recommended ESLint plugin:

image

In your case

declare const index: import('eslint').ESLint.Plugin & {
    configs: Record<'flat/recommended', 'recommended-typescript-flavor' /* and all other configs */, import('eslint').ESLint.ConfigData | {}>;
};
brettz9 commented 8 months ago

Should be fixed now in #1181 (and released in v47.0.1).

what1s1ove commented 8 months ago

Should be fixed now in #1181 (and released in v47.0.1).

image

Another error πŸ₯² Why is an empty object needed here?

image
brettz9 commented 8 months ago

Will users really need to get at rules like that? That {} is, IIRC, fudging things to avoid complaints about plugins: ["old-style-strings"].

what1s1ove commented 8 months ago

Will users really need to get at rules like that? That {} is, IIRC, fudging things to avoid complaints about plugins: ["old-style-strings"].

I modified it to the version recommended in the README (https://www.npmjs.com/package/eslint-plugin-jsdoc), and now it works πŸŽ‰ But honestly, I'm not very fond of how it looks now 😁

image

My other plugins look like this... but so far, ESLint itself doesn't know how to better incorporate them πŸ˜…

image
brettz9 commented 8 months ago

The problem with the latter is that the plugins themselves need to be reworked for flat config. A bit of a mess...

what1s1ove commented 8 months ago

The problem with the latter is that the plugins themselves need to be reworked for flat config. A bit of a mess...

As of now, I think everything is great, thank you for all you do!

Logicer16 commented 8 months ago

Just tried to use it but it seems we've incorrectly used ConfigData instead of FlatConfig for the flat configs.

error TS2322: Type '{} | ConfigData<RulesRecord>' is not assignable to type 'FlatConfig'.
  Type 'ConfigData<RulesRecord>' is not assignable to type 'FlatConfig'.
    Types of property 'plugins' are incompatible.
      Type 'string[] | undefined' is not assignable to type 'Record<string, Plugin> | undefined'.
        Type 'string[]' is not assignable to type 'Record<string, Plugin>'.
          Index signature for type 'string' is missing in type 'string[]'.
Logicer16 commented 8 months ago

I'm also experiencing a "double-default" issue when I have "moduleResolution": "NodeNext" in my tsconfig.json. This is just an issue with the types; runtime continues to work as expected. I am currently working around the issue with "moduleResolution": "Bundler".

brettz9 commented 8 months ago

Just tried to use it but it seems we've incorrectly used ConfigData instead of FlatConfig for the flat configs.

Ah yes, you're right. Fix should be applied shortly.

I'm also experiencing a "double-default" issue when I have "moduleResolution": "NodeNext" in my tsconfig.json. This is just an issue with the types; runtime continues to work as expected. I am currently working around the issue with "moduleResolution": "Bundler".

Can you indicate where you're seeing the error when you don't change the moduleResolution?

github-actions[bot] commented 8 months ago

:tada: This issue has been resolved in version 47.0.2 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

Logicer16 commented 8 months ago

Can you indicate where you're seeing the error when you don't change the moduleResolution?

src/index.ts:4:46 - error TS2339: Property 'configs' does not exist on type 'typeof import("~/Developer/a/node_modules/eslint-plugin-jsdoc/dist/index")'.

4 const jsdocConfig: Linter.FlatConfig = jsdoc.configs[
                                               ~~~~~~~

This builds without issue:

const jsdocConfig: Linter.FlatConfig = jsdoc.default.configs[
  "flat/recommended-typescript-flavor-error"
];

But fails at runtime:

const jsdocConfig = jsdoc.default.configs["flat/recommended-typescript-flavor-error"];
                                  ^

TypeError: Cannot read properties of undefined (reading 'configs')
    at file:///Users/jamesross/Developer/a/dist/index.js:2:35
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:113:12)

Node.js v20.10.0

If you need help reproducing, the following files are all it seems to need for the error to occur.

src/index.ts ```ts import jsdoc from "eslint-plugin-jsdoc"; import {Linter} from "eslint"; const jsdocConfig: Linter.FlatConfig = jsdoc.configs[ "flat/recommended-typescript-flavor-error" ]; ```
package.json ```json { "name": "a", "version": "1.0.0", "main": "index.js", "type": "module", "devDependencies": { "eslint": "^8.56.0", "eslint-plugin-jsdoc": "^47.0.2", "typescript": "^5.3.3" } } ```
tsconfig.json ```json { "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "dist" } } ```
brettz9 commented 8 months ago

Hmmm... I've confirmed the issue with your sample, but for some reason, we don't see the problem in regular "JavaScript-with-JSDoc-as-TypeScript" mode.

Adding the following to a JavaScript file:

import jsdoc from "eslint-plugin-jsdoc";

jsdoc.configs[
  "flat/recommended-typescript-flavor-error"
];

shows up with tooltip info properly:

image
brettz9 commented 8 months ago

It appears it can be fixed by our switching to native ESM (with fallback to CJS) (or by using babel's plugin for add-module-exports, but I think we'll go with the former).

what1s1ove commented 8 months ago

Hey @brettz9, all

Now it looks perfect! Thank you for all you do! Here is my migration PR - https://github.com/what1s1ove/whatislove.dev/pull/298

and here is my eslint.config.js - https://github.com/what1s1ove/whatislove.dev/blob/main/eslint.config.js

brettz9 commented 8 months ago

Can you indicate where you're seeing the error when you don't change the moduleResolution?

src/index.ts:4:46 - error TS2339: Property 'configs' does not exist on type 'typeof import("~/Developer/a/node_modules/eslint-plugin-jsdoc/dist/index")'.

4 const jsdocConfig: Linter.FlatConfig = jsdoc.configs[
                                               ~~~~~~~

Try release v48.0.1

Logicer16 commented 7 months ago

Try release v48.0.1

Sorry for the silence, just got around to checking and everything now seems to be working as expected. Thank you so much for all your work.