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
feat: validate type comments and generate .d.ts
#204
base: main
Are you sure you want to change the base?
Conversation
That's a good idea! |
Following up from this comment: eslint-community/eslint-plugin-n#169 (comment) I made a couple of utility changes to the .d.ts file I stole from your description 😄
|
I'll get around to update this PR real soon. One challenge right now is that this module support quite old versions of Node.js. I would prefer to align with That's a separate issue though, but one I would want to deal with before spending work on backporting changes to those older versions. cc @JoshuaKGoldberg, would be lovely with some |
Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com>
rules: { | ||
semi: ["error", "never"], | ||
"semi-spacing": ["error", { before: false, after: true }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's something deeply funny to me about an eslint-community
project using ESLint for formatting.
"coverage": "opener ./coverage/lcov-report/index.html", | ||
"docs:build": "vitepress build docs", | ||
"docs:watch": "vitepress dev docs", | ||
"format": "npm run -s format:prettier -- --write", | ||
"format:prettier": "prettier .", | ||
"format:check": "npm run -s format:prettier -- --check", | ||
"lint": "eslint .", | ||
"lint:eslint": "eslint .", | ||
"lint:tsc": "tsc", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming: I wouldn't call TypeScript a "lint" task. Even if it acts essentially as a linter in this setup, I've found it confusing for newer contributors to see it named as one.
const operations = Object.freeze({ | ||
ArrayExpression(node, initialScope) { | ||
if (node.type !== "ArrayExpression") { | ||
return null | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 are these if
s actually necessary, or just to appease a type checker that doesn't understand what's happening?
If it's the latter, the general right thing to do would be to fix TypeScript's understanding of the types so it doesn't yell at you.
For posterity: I tried adding /** @param {import("estree").ArrayExpression} node */
to the ArrayExpression
one and got a type error on operations
:
Type 'Readonly<{ ArrayExpression(node: ArrayExpression, initialScope: Scope | undefined): { value: any[]; } | null; AssignmentExpression(node: Node, initialScope: Scope | undefined): StaticValue | null; ... 14 more ...; UnaryExpression(node: Node, initialScope: Scope | undefined): { ...; } | ... 3 more ... | null; }>' is not assignable to type 'Readonly<Partial<Record<"CatchClause" | "ClassBody" | "Identifier" | "Literal" | "MethodDefinition" | "PrivateIdentifier" | "Program" | "Property" | "PropertyDefinition" | "SpreadElement" | ... 60 more ... | "VariableDeclaration", VisitorCallback>>>'.
Types of property 'ArrayExpression' are incompatible.
Type '(node: ArrayExpression, initialScope: Scope | undefined) => { value: any[]; } | null' is not assignable to type 'VisitorCallback'.ts(2322)
Tricky.
I got around it by:
- Renaming
types.mjs
totypes.d.ts
, so I could use "real" TypeScript syntax and not the annoying JSDoc sludge - Making the
VisitorCallback
type generic:
export type VisitorCallback<InNode extends Node> = (
node: InNode,
initialScope: eslint.Scope.Scope | undefined,
) => StaticValue | null
- Using a type annotation on the
ArrayExpression
member:
/** @type {Readonly<Partial<Record<import('eslint').Rule.NodeTypes, import("./types.js").VisitorCallback<any>>>>} */
const operations = Object.freeze({
/** @type {import("./types.js").VisitorCallback<import("estree").ArrayExpression>} */
ArrayExpression(node, initialScope) {
YMMV.
This is an alternative to #60 which also fixes #150
As this PR doesn't rewrite to TS its easier to keep up to date as other changes happen.
No files has been renamed, the build script remains largely the same, the code as well mostly.
The generated type file