Skip to content

refactor: migrate type declarations to use the @import syntax #367

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

Conversation

lumirlumir
Copy link
Member

@lumirlumir lumirlumir commented May 9, 2025

Prerequisites checklist

What is the purpose of this pull request?

Hello,

In this PR, I’ve migrated the type declarations to use the @import syntax and added support for MessageIds.

This change was briefly discussed in #336 (comment).

I believe this migration will help ensure consistent type declarations across plugin repositories.

However, one concern I have is that the type module path for RuleModule and MarkdownRuleDefinition has changed from @eslint/markdown to @eslint/markdown/types. While this path is already used in the CSS and JSON plugins, I’m worried it could introduce a breaking change.

I’d appreciate any suggestions on how to avoid making this a breaking change, if possible.

What changes did you make? (Give an overview)

I’ve migrated the type declarations to use the @import syntax and added support for MessageIds.

Related Issues

ref: #336 (comment)

Is there anything you'd like reviewers to focus on?

Prerequisite

@lumirlumir lumirlumir marked this pull request as draft May 9, 2025 06:59
@lumirlumir lumirlumir added this to Triage May 9, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in Triage May 9, 2025
@lumirlumir lumirlumir moved this from Needs Triage to Implementing in Triage May 9, 2025
Copy link
Member Author

Choose a reason for hiding this comment

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

I've followed the script from JSON.

@lumirlumir lumirlumir marked this pull request as ready for review May 9, 2025 11:26
@lumirlumir lumirlumir requested a review from fasttime May 9, 2025 11:27
@lumirlumir lumirlumir changed the title refactor: align rule typedefs with conventions from other plugins refactor: migrate type declarations to use the @import syntax May 9, 2025
@lumirlumir lumirlumir self-assigned this May 9, 2025
@lumirlumir lumirlumir marked this pull request as draft May 10, 2025 08:45
@lumirlumir lumirlumir requested review from nzakas and snitin315 June 21, 2025 11:52
@lumirlumir
Copy link
Member Author

The missing type checking issue reported in #432 has been addressed in this PR, so type checking now works as expected for all files.

src/index.js Outdated
* @typedef {import("./types.ts").MarkdownRuleDefinition<Options>} MarkdownRuleDefinition<Options>
* @template {Partial<import("./types.ts").MarkdownRuleDefinitionTypeOptions>} [Options={}]
* @import { Linter } from "eslint";
* @import { MarkdownRuleVisitor as MRV, MarkdownRuleDefinition as MRD, MarkdownRuleDefinitionTypeOptions } from "./types.js";
Copy link
Member

Choose a reason for hiding this comment

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

Can we just use the regular names? I think that makes things a lot easier to understand.

Suggested change
* @import { MarkdownRuleVisitor as MRV, MarkdownRuleDefinition as MRD, MarkdownRuleDefinitionTypeOptions } from "./types.js";
* @import { MarkdownRuleVisitor , MarkdownRuleDefinition, MarkdownRuleDefinitionTypeOptions } from "./types.js";

Copy link
Member Author

@lumirlumir lumirlumir Jun 23, 2025

Choose a reason for hiding this comment

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

I initially tried using the original name, but without an alias, it results in a duplicate type definitions error when running the tsc command, since the same name is declared again in the following lines using the @typedef syntax.

(This redeclaration is intentional, for the reason I mentioned here.)

However, if we decide to remove these types from the @eslint/markdown export path and move them to the @eslint/markdown/types path, then these lines can be safely removed. (ref: here)

Copy link
Member

Choose a reason for hiding this comment

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

Maybe instead of renaming the imported types we could import the whole types module as a namespace to avoid the naming collision? I.e:

/**
 * @import { Linter } from "eslint";
 * @import * as Types from "./types.js";
 * @typedef {Linter.RulesRecord} RulesRecord
 * @typedef {Types.MarkdownRuleDefinition} RuleModule
 * @typedef {Types.MarkdownRuleVisitor} MarkdownRuleVisitor
 */

And similarly for the MarkdownRuleDefinition typedef below.

Copy link
Member Author

Choose a reason for hiding this comment

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

Awesome, it works 👍

I've added a new commit a001891

src/index.js Outdated
Comment on lines 25 to 29
* @typedef {MRV} MarkdownRuleVisitor
*/

/**
* @typedef {MRD<Options>} MarkdownRuleDefinition<Options>
Copy link
Member

Choose a reason for hiding this comment

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

Then I don't think we need these.

Copy link
Member Author

@lumirlumir lumirlumir Jun 23, 2025

Choose a reason for hiding this comment

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

This is because the type tests in types.test.js currently depend on these type definitions.
So, removing them in this PR would introduce a breaking change:

import markdown, {
MarkdownSourceCode,
MarkdownRuleDefinition,
MarkdownRuleVisitor,
type RuleModule,
} from "@eslint/markdown";

Personally, I think it would be better to keep this PR non-breaking and create a separate PR to remove these types and move them under the @eslint/markdown/types path when importing.

Both the JSON and CSS plugins follow a similar approach, so it would make sense to organize the types this way:

If it’s acceptable, I can open a separate PR with the breaking changes by tomorrow.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good. Because the next release will be a major release, this is the time to get all the breaking changes in. 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

I've made a separate PR #446 👍

@lumirlumir lumirlumir requested a review from nzakas June 25, 2025 05:54
*/

/**
* @typedef {Types.MarkdownRuleDefinition<Options>} MarkdownRuleDefinition<Options>
Copy link
Member Author

Choose a reason for hiding this comment

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

Suggested change
* @typedef {Types.MarkdownRuleDefinition<Options>} MarkdownRuleDefinition<Options>
* @typedef {Types.MarkdownRuleDefinition<Options>} MarkdownRuleDefinition<Options>

This line should be separated from the typedefs above; otherwise, it causes a type error like the one below:

image

fasttime
fasttime previously approved these changes Jun 26, 2025
Copy link
Member

@fasttime fasttime left a comment

Choose a reason for hiding this comment

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

LGTM, thanks! Leaving open for @nzakas to verify before merging.

@fasttime fasttime moved this from Implementing to Second Review Needed in Triage Jun 26, 2025
snitin315
snitin315 previously approved these changes Jun 26, 2025
Copy link
Contributor

@snitin315 snitin315 left a comment

Choose a reason for hiding this comment

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

LGTM

@JoshuaKGoldberg
Copy link
Contributor

@eslint/markdown/types ... already used in the CSS and JSON plugins

👋 I'm catching up on this PR now and there's a lot of context. But I can't find where the original decision on that was made. Was there a driving reason to put types in the specific /types export? This is pretty unusual.

@fasttime
Copy link
Member

@eslint/markdown/types ... already used in the CSS and JSON plugins

👋 I'm catching up on this PR now and there's a lot of context. But I can't find where the original decision on that was made. Was there a driving reason to put types in the specific /types export? This is pretty unusual.

@JoshuaKGoldberg There was a discussion in eslint/json#84. Do you know a better solution? I have to admit I haven't seen our approach used anywhere else.

@JoshuaKGoldberg
Copy link
Contributor

Ah, I'd missed that PR. Darn.

Generally, projects try to in order of preference:

  1. Not auto-generate types, so they can be directly exported from the root export
  2. Have type auto-generation always run before publish, so they can still be exported from the root export

From eslint/json#82 (comment):

there's no easy way to just say "export this type"

Just to confirm, is the issue that index.js needs to export types from its sibling types.ts - and there's no way in TypeScript's JSDoc support to "re-export" a type in a JS file?

I haven't dug too deep, but the first thing that comes to mind is injecting an \nexport type * from "./types.d.ts"; at the bottom of the dist/*/index.d.ts files. That would do it in a pinch.

@lumirlumir
Copy link
Member Author

@fasttime @JoshuaKGoldberg

Hi everyone, is there anything I need to do on my side? If so, I’d be happy to take a look.

@JoshuaKGoldberg
Copy link
Contributor

JoshuaKGoldberg commented Jun 30, 2025

I don't know what the right next step is 😅. #453 is a reference for the alternate strategy of adding a re-export line.

I also asked for help in the TypeScript Discord to see if there's a better way: https://discord.com/channels/508357248330760243/1389274620212809829

Edit: and Bluesky, https://bsky.app/profile/did:plc:hwtki3j7oghodc7h6gqnrtro/post/3lsu2bsv4gs2w

@lumirlumir lumirlumir dismissed stale reviews from snitin315 and fasttime via 7e3f031 July 1, 2025 14:38
@lumirlumir
Copy link
Member Author

@JoshuaKGoldberg Thanks for the references!

I’ve explored some alternatives, but I think #453 is the best solution for now 👍


@nzakas I’d appreciate it if you could take a final look when you have time 😄

(FYI, I’ve resolved the merge conflicts, so the previous review has gone stale)

@nzakas
Copy link
Member

nzakas commented Jul 2, 2025

Given that we've already followed the /types approach in @eslint/json, I think it's fine to keep it here. We can always revisit later if we decide there's a cleaner approach and then apply that all of the plugins.

@nzakas nzakas merged commit 0afc924 into main Jul 2, 2025
21 checks passed
@nzakas nzakas deleted the refactor-align-rule-type-definitions-with-conventions-from-other-plugins branch July 2, 2025 15:06
@github-project-automation github-project-automation bot moved this from Second Review Needed to Complete in Triage Jul 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Complete
Development

Successfully merging this pull request may close these issues.

5 participants