Change Request: Allow `SourceCode#getText()` types to accept tokens and comments
ESLint version
v10.10.0
What problem do you want to solve?
I found this while looking through a rule file in the eslint-community. The file uses @ts-expect-error when passing a comment to SourceCode#getText().
The type definition of SourceCode#getText() only accepts an ESTree.Node.
getText(
node?: ESTree.Node,
beforeCount?: number,
afterCount?: number,
): string;Other SourceCode methods return AST.Token and ESTree.Comment values.
const token = sourceCode.getFirstToken(node);
// AST.Token | null
const comments = sourceCode.getCommentsBefore(node);
// ESTree.Comment[]Despite this type definition, getText() can also accept these values because its implementation only reads the provided object's range.
getText(node, beforeCount, afterCount) {
if (node) {
return this.text.slice(
Math.max(node.range[0] - (beforeCount || 0), 0),
node.range[1] + (afterCount || 0),
);
}
return this.text;
}So, this causes valid runtime code to fail type checking.
const token = sourceCode.getFirstToken(node);
if (token) {
// Argument of type 'Token' is not assignable to parameter of type 'Node | undefined'.
sourceCode.getText(token);
}
for (const comment of sourceCode.getCommentsBefore(node)) {
// Argument of type 'Comment' is not assignable to parameter of type 'Node | undefined'.
sourceCode.getText(comment);
}This means that values returned by SourceCode itself cannot be passed back to getText() without a type error, even though they are handled at runtime.
I also found examples of this usage in ESLint.
- The
curlyrule passes a token returned bygetTokenBefore()togetText(). - A
SourceCodetest passes a shebang comment returned bygetAllComments()togetText().
And found similar usages in ecosystem plugins.
eslint-plugin-npasses a comment togetText()and uses@ts-expect-errorto suppress the resulting type error.eslint-plugin-typescript-sort-keyspasses a comment togetText()usingcomment as any. removing the type assertion reproduces the same error.eslint-plugin-espassed a token togetText()as part of an Espree compatibility workaround.eslint-stylisticalso passes a token togetText()(without a type error because it uses@typescript-eslint'sSourceCodetype that already acceptsNode | Token).
What do you think is the correct solution?
I think we can update SourceCode#getText() to accept nodes, tokens, and comments.
getText(
syntaxElement?: ESTree.Node | AST.Token | ESTree.Comment,
beforeCount?: number,
afterCount?: number,
): string;This would be a type widening and would not require a runtime implementation change.
Type tests can cover all three supported inputs.
sourceCode.getText(AST);
sourceCode.getText(TOKEN);
sourceCode.getText(COMMENT);The documentation and implementation JSDoc can also be updated to describe the parameter as a node, token, or comment.
Participation
- I am willing to submit a pull request for this change.
AI acknowledgment
- I did not use AI to generate this issue report.
- (If the above is not checked) I have reviewed the AI-generated content before submitting.
Additional comments
No response
Disclosure: I'm a participant of open source contribution program OSSCA
Source: eslint/eslint