ota-meshi / eslint-plugin-astro

ESLint plugin for Astro component
https://ota-meshi.github.io/eslint-plugin-astro/
MIT License
320 stars 26 forks source link

JSX return type and @typescript-eslint/no-unsafe-return #168

Closed david-abell closed 9 months ago

david-abell commented 1 year ago

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

What version of ESLint are you using?

8.33.0

What version of eslint-plugin-astro are you using?

0.23.0

What did you do?

Configuration .eslintrc.json ``` { "env": { "browser": true, "node": true }, "extends": [ // ... "plugin:astro/recommended", "eslint:recommended", "plugin:jsx-a11y/recommended", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking", "prettier" ], // ... "parser": "@typescript-eslint/parser", "parserOptions": { "project": "./tsconfig.eslint.json" }, "overrides": [ { "files": ["*.astro"], "parser": "astro-eslint-parser", "parserOptions": { "parser": "@typescript-eslint/parser", "extraFileExtensions": [".astro"], "project": "./tsconfig.eslint.json" }, "rules": { // override/add rules settings here, such as: // "astro/no-set-html-directive": "error" // "no-plusplus": "off", "no-restricted-syntax": [ "error", "ForInStatement", "LabeledStatement", "WithStatement" ] } } // ... ] } ```
Configuration tsconfig.eslint.json ``` { "extends": "./tsconfig.json", "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.js", "src/**/*.jsx", "src/**/*.astro", "test/**/*.ts", "globals.d.ts", "astro.config.mjs" ] } ```

Example .astro file

---
    let cards = [
  {
    href: "https://docs.astro.build/",
    title: "Documentation",
    body: "Learn how Astro works and explore the official API docs.",
  },
  {
    href: "https://astro.build/integrations/",
    title: "Integrations",
    body: "Supercharge your project with new frameworks and libraries.",
  },
  {
    href: "https://astro.build/themes/",
    title: "Themes",
    body: "Explore a galaxy of community-built starter themes.",
  },
];
---

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
        <meta name="viewport" content="width=device-width" />
        <meta name="generator" content={Astro.generator} />
        <title>Astro</title>
    </head>
    <body>
    <li>
  {
    cards.map((card) => (
      // next line has following error: Unsafe return of an `any` typed value. eslint(@typescript-eslint/no-unsafe-return)
      <div>{card.href}</div>
    ))
  }
</li>
    <div class="tags">
    {
      ["a", "b", "c"].map((tag) => (
        <p class={tag}>Tag:{tag} This p tag triggers unsafe return of an `any` typed value.</p>
      ))
    }
  </div>
    </body>
</html>

What did you expect to happen?

no error

What actually happened?

Unsafe return of an any typed value.eslint@typescript-eslint/no-unsafe-return

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-tekdct?file=src/pages/index.astro

Additional comments

run npx eslint src/pages/index.astro on linked stackblitz example for error in action.

Referred to file issue here from Astro https://github.com/withastro/astro/issues/6280#issue-1589534043

ota-meshi commented 1 year ago

stackblitz is not suitable for reproduction. I can't debug Node.js. Could you provide it on GitHubRepo? Also include the lint command in your package.json. I can debug Node.js using Codespaces.

david-abell commented 1 year ago

Repo is https://github.com/david-abell/astro-jsx-no-unsafe

Script is lint in package.json

Let me know if there is anything else I can help with

ota-meshi commented 1 year ago

I think it can be solved by adding a d.ts file like the following and including the d.ts file in tsconfig.eslint.json.

import 'astro/astro-jsx'

declare global {
    namespace JSX {
        type Element = HTMLElement
        // type Element = astroHTML.JSX.Element // We want to use this, but it is defined as any.
        type IntrinsicElements = astroHTML.JSX.IntrinsicElements
    }
}
david-abell commented 1 year ago

This seems to be the solution.

JSX types appear to not be imported if no JSX framework is included in the project.

I tested out The official minimal React template and it does not require importing and declaring the JSX namespace like this to work properly with eslint-plugin-astro

If others encounter this, the specific minimal setup that worked for me was the above recommended d.ts namespace declaration and the below configurations:

eslintrc.cjs

module.exports = {
  // The plugins and shared settings I was testing
  plugins: ["jsx-a11y", "@typescript-eslint"],
  extends: [
    // ...
    "eslint:recommended",
    "plugin:astro/recommended",
    "plugin:jsx-a11y/recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
    "prettier",
  ],
 // This was needed because parser and parser options can get overridden by shareable configurations 
  parser: "@typescript-eslint/parser",
  parserOptions: {
    project: "./tsconfig.eslint.json",
    extraFileExtensions: [".astro"],
  },
  //  This is needed for a cjs configuration file since the project type in package.json is set as "module"
  env: {
    node: true,
  },
  // This is the default recommended overrides for eslint-plugin-astro
  overrides: [
    {
      // Define the configuration for `.astro` file.
      files: ["*.astro"],
      // Allows Astro components to be parsed.
      parser: "astro-eslint-parser",
      // Parse the script in `.astro` as TypeScript by adding the following configuration.
      // It's the setting you need when using TypeScript.
      parserOptions: {
        parser: "@typescript-eslint/parser",
        extraFileExtensions: [".astro"],
      },
      rules: {
        // override/add rules settings here, such as:
        // "astro/no-set-html-directive": "error"
      },
    },
    // ...
  ],
};

tsconfig.eslint.json

{
  "extends": "./tsconfig.json",
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.js",
    "src/**/*.jsx",
    "src/**/*.astro",
    "astro.config.mjs",
    ".eslintrc.cjs",
    "d.ts"
  ]
}
saibotk commented 9 months ago

Should we maybe consider adding this as a hint to the Readme? I just stumbled upon the same "problem"