Using TypeScript and Maquette JSX but linter says 'jsx' is unused

102 views Asked by At

I am using TypeScript and Maquette to compile .tsx files. The code compiles correctly and runs in the browser, but ESLint is unhappy with my jsx function, flagging it as an "unused var".

I tried to mimic the TypeScript Maquette starter project as closely as possible, but when I look at that project I don't see the linter warning. Somehow, in the starter project, ESLint and TypeScript recognize that jsx is my factory function, but in my project, despite what seems to me to be identical configuration, it doesn't.

What's my missing piece of the puzzle? Despite reading all the docs several times and Googling this every way I could imagine, I haven't found anything that's identified the cause of the issue.

badge.tsx

import { jsx } from "maquette-jsx";
import { VNode } from "maquette";
import Component from "../../core/component";

export default class Badge extends Component {
    init():void {}

    renderVDom():VNode {
        const {
            gc,
            state: { label },
        } = this;

        return (
            <div key={this} class={gc("badge")} title={label}>
                { label }
            </div>
        );
    }
}

But when I run eslint (./node_modules/.bin/eslint . --ext .json,.js,.ts,.jsx,.tsx) I get the following warning:

.../js/components/badge/badge.tsx
  1:10  warning  'jsx' is defined but never used  @typescript-eslint/no-unused-vars

I'm including my config files below but it's a big project so I'm editing out the parts I feel aren't relevant:

package.json

{
  "name": "...",
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^4.25.0",
    "@typescript-eslint/parser": "^4.25.0",
    "eslint": "7.7.x",
    "maquette-jsx": "^3.0.1",
    "ts-loader": "^8.3.0",
    "typescript": "^4.2.4"
  },
  "dependencies": {
    "maquette": "^3.5.0"
  }
}

tsconfig.json

{
    "include": [
        "./js/**/*.ts",
        "./js/**/*.tsx"
    ],
    "compilerOptions": {
        "jsx": "react",
        "jsxFactory": "jsx",
        "module": "es6",
        "moduleResolution": "node",
        "noImplicitAny": true,
        "outDir": "./dist/",
        "resolveJsonModule": true,
        "target": "es6",
        "lib": [
            "DOM",
            "ES2020"
        ]
    }
}

.eslintrc.json

{  
  "env": {
    "browser": true,
    "es6": true
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module"
  },
  "plugins": [
    "@typescript-eslint"
  ],
  "extends": [
    "./.typescript.eslintrc.json"
  ]
}

.typescript.eslintrc.json

{
    "overrides": [
        {
            "files": ["*.ts", "*.tsx"],
            "rules": {
                "@typescript-eslint/no-unused-vars": "warn",

                "no-unused-vars": "off"
            }
        }
    ]
}
1

There are 1 answers

0
JDB On

The missing piece of the puzzle is the parserOptions.project.

Actually, parserOptions.jsxPragma is also acceptable, but as the fragment name ("jsx") is already defined in the project, and the linter is able to get other useful information from the tsconfig file, it often makes more sense to set project if you can.

{
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module",
    "project": "./tsconfig.json"
  },  
}

The project points ESLint to the TypeScript configuration file which is critical for identifying the implicit call to jsx().

However, if linking your tsconfig to your eslint results in performance issues, then you can scale back and just use jsxPragma:

{
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module",
    "jsxPragma": "jsx"
  },
}

To my knowledge, the typescript-parser options are only documented on the NPM module Readme. It's probably recorded elsewhere, but a quick search of the usual places™ didn't turn up any detailed docs.