Description
Which packages would you like to change?
-
@eslint/compat
-
@eslint/config-array
-
@eslint/core
-
@eslint/migrate-config
-
@eslint/object-schema
-
@eslint/plugin-kit
What problem do you want to solve?
The RuleVisitor
interface is currently defined as follows:
export interface RuleVisitor {
/**
* Called for each node in the AST or at specific times during the traversal.
*/
[key: string]: (...args: any[]) => void;
}
However, this is causing problems when trying to extend RuleVisitor
under strict
TypeScript mode, as seen in these PRs:
- fix: Use updated types from @eslint/core json#66
- fix: Bring types in sync with @eslint/core eslint#19157
The errors take the form of the following:
error TS2411: Property 'Document' of type '((node: DocumentNode$1) => void) | undefined' is not assignable to 'string' index type '(...args: any[]) => void'.
What do you think is the correct solution?
The problem is that the method defined in RuleVisitor
is not optional.
I can see a few different options:
- Remove all methods. We can remove any predefined methods from
RuleVisitor
and leave essentially a blank interface:
export interface RuleVisitor {
/**
* Called for each node in the AST or at specific times during the traversal.
*/
- [key: string]: (...args: any[]) => void;
}
That would give consumers something to extend from so that it logically looks like there's some relationship between the core types and consumer types. I'm not sure it's valuable.
- export interface RuleVisitor {
+ export type RuleVisitor = {
/**
* Called for each node in the AST or at specific times during the traversal.
*/
- [key: string]: (...args: any[]) => void;
+ [key in string]?: (...args: any[]) => void;
}
Defining all methods to be optional also seems to make RuleVisitor
mostly useless.
- Eliminate
RuleVisitor
interface completely. Because we don't know what the visitor will look like for any particular language, maybe it's a bad idea to try and enforce anything in particular. We could just define theRuleDefinitionTypeOptions#Visitor
asObject
, which would allow any non-primitive type to be used, and then we don't needRuleVisitor
at all:
export interface RuleDefinitionTypeOptions {
LangOptions: LanguageOptions;
Code: SourceCode;
RuleOptions: unknown[];
- Visitor: RuleVisitor;
+ Visitor: Object;
Node: unknown;
MessageIds: string;
ExtRuleDocs: unknown;
}
I think this is my favorite approach, but I'd like some insights from @JoshuaKGoldberg and @fasttime on all of the options and their ramifications.
Participation
- I am willing to submit a pull request for this change.
Additional comments
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Complete