Skip to content

Bug: Created rules using RuleCreator are not portable #5032

@Andarist

Description

@Andarist

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.
  • I have searched for related issues and found none that matched my issue.
  • I have read the FAQ and my problem is not listed.

Relevant Package

utils

Playground Link

No response

Repro Code

const createRule = ESLintUtils.RuleCreator(name => {
  const ruleName = parsePath(name).name

  return `${REPO_URL}/blob/@emotion/eslint-plugin@${version}/packages/eslint-plugin/docs/rules/${ruleName}.md`
})

// it isn't a problem with `createRule<never[], keyof typeof messages>({`
createRule({
  name: __filename,
  meta: {
    docs: {
      description: 'Ensure vanilla emotion is not used',
      recommended: false
    },
    messages: {
      vanillaEmotion: 'Vanilla emotion should not be used'
    },
    schema: [],
    type: 'problem'
  },
  defaultOptions: [],
  create(context) {
    return {
      ImportDeclaration(node) {
        if (node.source.value === '@emotion/css') {
          context.report({
            node: node.source,
            messageId: 'vanillaEmotion'
          })
        }
      }
    }
  }
})

ESLint Config

No response

tsconfig

No response

Expected Result

A definition file for a library utilizing this util should be generated just fine.

Actual Result

We get an error like this one:

TS2742: The inferred type of 'rules' cannot be named without a reference to '@typescript-eslint/utils/node_modules/@typescript-eslint/types/dist/generated/ast-spec'. This is likely not portable. A type annotation is necessary.

I've diagnosed this and the problem is that the final RuleModule contains a reference to TRuleListener and its type contains references to types from another packages:

I've also figured out a workaround - we need to provide generic params explicitly, to disable the inference for the third generic param (TRuleListener) and just use its default. The workaround in practice can be checked out here: https://github.com/emotion-js/emotion/pull/2761/files/79848d3a5ff7fa5338d31a27fb94951ea15071fa

I wonder though... why the TRuleListener is a generic? Does it have to be referenced in RuleModule? I would have assumed that a rule should be rather opaque to the consumer 🤔 (at least in relation to what kind of AST types does it process and stuff like that)

cc @JoshuaKGoldberg, funny enough that I've stumbled upon this issue just after this recent conversation on Twitter: https://twitter.com/JoshuaKGoldberg/status/1526969335717191692 😅

Additional Info

No response

Versions

package version
@typescript-eslint/utils 5.25.0
TypeScript 4.5.5
ESLint ^7.10.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    accepting prsGo ahead, send a pull request that resolves this issuebreaking changeThis change will require a new major version to be releasedbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy