Skip to content

Add lint rule to validate type descriptions in README#1396

Merged
sindresorhus merged 22 commits into
mainfrom
feat/lint-rule-to-validate-readme-against-jsdoc
Apr 13, 2026
Merged

Add lint rule to validate type descriptions in README#1396
sindresorhus merged 22 commits into
mainfrom
feat/lint-rule-to-validate-readme-against-jsdoc

Conversation

@som-sm

@som-sm som-sm commented Mar 31, 2026

Copy link
Copy Markdown
Collaborator

This PR adds a lint rule that enforces that type descriptions in the README exactly match the first line of their source JSDoc.

readme-jsdoc-lint-rule-demo.mov

The lint caught around 60 mismatches in the existing README file.

Repository owner deleted a comment from claude Bot Mar 31, 2026
Repository owner deleted a comment from claude Bot Mar 31, 2026
@som-sm

som-sm commented Mar 31, 2026

Copy link
Copy Markdown
Collaborator Author

xo.config.js uses the FlatXoConfig type from xo, and FlatXoConfig itself relies on eslint types. However, those eslint types are being incorrectly resolved from @types/eslint, which is causing errors in the config.

I’ve opened a discussion in the ESLint repository about this: eslint/eslint#20704.

@som-sm
som-sm force-pushed the feat/lint-rule-to-validate-readme-against-jsdoc branch from b9e8ca8 to 9404a76 Compare April 10, 2026 15:18
som-sm added 6 commits April 11, 2026 13:31
Enabling `"types": ["node"]` globally is risky because a source `.d.ts` file may silently depend on Node.js types. It will compile fine in this repo (since `@types/node` is installed as a dev dependency) but break for consumers who do not have `@types/node`.
Repository owner deleted a comment from claude Bot Apr 11, 2026
Repository owner deleted a comment from claude Bot Apr 11, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
@som-sm
som-sm force-pushed the feat/lint-rule-to-validate-readme-against-jsdoc branch 2 times, most recently from cf95d5d to 7d63f4c Compare April 12, 2026 10:48
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
@som-sm
som-sm force-pushed the feat/lint-rule-to-validate-readme-against-jsdoc branch from 7d63f4c to 4a608a8 Compare April 12, 2026 11:21
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 12, 2026
Repository owner deleted a comment from claude Bot Apr 13, 2026
@@ -1,5 +1,5 @@
/**
Given a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) return the {@link Primitive | primitive type} it belongs to, or `never` if it's not a primitive.
Given a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) return the [primitive type](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) it belongs to, or `never` if it's not a primitive.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the link to an external link, because otherwise the README description would need manual adjusting because it'd be really complicated to automatically figure out where a particular symbol lives.

If a symbol link is absolutely required, then we'd have to disable the lint-rule for that specific list item and adjust the description manually, as mentioned here:

const tagRegex = /\{@link\s+([^\}]+)\}/gv;
// This simply replaces "{@link SymbolName}" with "`SymbolName`".
// It doesn't handle captions or external links, for example, "{@link SymbolName | some caption}" simply becomes "`SymbolName | some caption`".
// For external links, markdown syntax should be used, like "[type-fest](https://github.com/sindresorhus/type-fest)".
// And for symbols, if just "`SymbolName`" isn't sufficient, then for those specific cases this rule should be disabled.
jsdocDescription = jsdocDescription.replaceAll(tagRegex, (_, content) => `\`${content}\``);

Comment thread xo.config.js
import {jsdocCodeblocksProcessor} from './lint-processors/jsdoc-codeblocks.js';

/** @type {import('xo').FlatXoConfig} */
/** @type {Array<import('eslint').Linter.Config>} */

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to switch to eslint type because of this issue.

Comment thread package.json Outdated
"test:tsc": "node --max-old-space-size=6144 ./node_modules/.bin/tsc",
"test:tsd": "node --max-old-space-size=6144 ./node_modules/.bin/tsd",
"test:xo": "node --max-old-space-size=6144 ./node_modules/.bin/xo --ignores=lint-processors/fixtures/**/*.d.ts",
"test:xo": "node --max-old-space-size=6144 ./node_modules/.bin/xo --ignores=lint-processors/fixtures/**/*.d.ts '**/*.{js,ts}' readme.md",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because XO doesn't seem to lint .md files even if there's an entry for .md files in the config.

@som-sm

som-sm commented Apr 13, 2026

Copy link
Copy Markdown
Collaborator Author

I initially expected only minor discrepancies between the README and JSDoc descriptions, such as typos. However, there were several instances where the two were entirely different. So, I had to review them manually and select the better version. And at certain places, I had to make changes beyond just picking between the two.

As a result, for some types, the JSDoc description has changed, while for some others, the README description has changed. And for some, both have changed.

@som-sm
som-sm marked this pull request as ready for review April 13, 2026 15:01
@som-sm
som-sm requested a review from sindresorhus April 13, 2026 15:01
@sindresorhus
sindresorhus merged commit d0bbbbe into main Apr 13, 2026
11 checks passed
@sindresorhus
sindresorhus deleted the feat/lint-rule-to-validate-readme-against-jsdoc branch April 13, 2026 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants