Skip to content
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

Add TypeScript type-checking to all JavaScript files and publish utility types #723

Merged
merged 1 commit into from
Aug 23, 2022

Conversation

bmish
Copy link
Collaborator

@bmish bmish commented Aug 20, 2022

What this does:

  • Uses jsdoc type annotations to type-check JavaScript code using the TypeScript checkJs option.
  • Refactors code to be easier for TypeScript to understand where necessary.
  • Fixes potentially-unsafe code caught by TypeScript.
  • Exports type declarations for anyone wanting to import/use our utils in TypeScript code.
  • This does not actually convert any code to TypeScript. If we wanted to that at some point, it should be a lot easier after this.

Benefits:

  • Uncovers and fixes bugs and crashes in unsafe lint rule implementations
  • Provides autocomplete and hover-over documentation so you can easily understand the structure of the abstract syntax tree (AST) while implementing lint rules
  • Generally easier lint rule development will help make linting accessible to more developers

Issues I ran into:

  • Had to ts-ignore that messageId can be passed as undefined to ESLint's context.report()
  • Couldn't find types for @babel/eslint-parser and had to manually create some in global.d.ts
  • Right now, the package will only be published with the type declarations from dist/lib/index.d.ts which only has useful types for utils but not for rules/configs due to the usage of requireIndex. If we got rid of requireIndex and included all of dist/ in the package then the types for the rules/configs should work too. We can consider that later if there's a need.

@bmish bmish added the bug Something isn't working label Aug 20, 2022
@bmish bmish force-pushed the ts-checkjs branch 2 times, most recently from 0577ba6 to 0e79ede Compare August 20, 2022 18:55
@bmish bmish changed the title Add TypeScript type-checking to all JavaScript files Add TypeScript type-checking to all JavaScript files and export types Aug 20, 2022
@bmish bmish added enhancement New feature or request and removed bug Something isn't working labels Aug 20, 2022
@bmish bmish changed the title Add TypeScript type-checking to all JavaScript files and export types Add TypeScript type-checking to all JavaScript files and publish utility types Aug 20, 2022
@bmish bmish requested a review from mongoose700 August 20, 2022 20:33
@@ -35,6 +34,7 @@ module.exports = {
};

for (const { node } of tracker.iterateGlobalReferences(traceMap)) {
// @ts-ignore -- ESLint adds `parent` to each node.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it be possible to use declare module to tell it about the parent?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So it should be yes but I'll admit it's tricky to figure out how to use declare module 'eslint-utils' to continue exporting all the same types but just tweaking the return value of one function inside one of the exported classes. If this is a bug in @types/eslint-utils, it would be better to fix it there of course, will share a PR to attempt that soon.

Copy link
Collaborator Author

@bmish bmish Aug 22, 2022

Choose a reason for hiding this comment

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

Here is the fix to @types/eslint-utils: DefinitelyTyped/DefinitelyTyped#61870. Will wait for this to merge.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Published in @types/eslint-utils 3.0.2 and updated.

@@ -80,6 +80,10 @@ module.exports = {
{
messageId: 'suggest',
fix(fixer) {
if (!node.range || !node.argument || !node.argument.range) {
// The if statement is just to make TypeScript happy.
Copy link
Collaborator

Choose a reason for hiding this comment

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

In that case, would it be better to throw an error instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Shouldn't matter too much but I updated to an exception.

function isT(node, importedTranslationMethodName) {
// Example: import { t } from 'intl'; t(...);
return (
node.type === 'CallExpression' &&
isIdentifier(node.callee) &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this form of comments not support node is Identifier? That would be really helpful for narrowing down what other things the node could have.

Copy link
Collaborator Author

@bmish bmish Aug 22, 2022

Choose a reason for hiding this comment

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

So yes I found out that that syntax is possible: https://github.com/open-wc/open-wc/blob/50e0ed588c67d516cb109f4106186265c239e218/packages/eslint-plugin-lit-a11y/lib/utils/aria.js#L25

But I've wanted to move away from these trivial helper functions for checking node types anyway. And removing unnecessary helper functions makes the code easier for TypeScript to understand in general.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants