Search code examples
typescriptintellij-ideawebpackeslintsolid-js

Why function returns JSX.Element is not assignable to variable type Component in SolidJS?


My IDE (IntelliJ IDEA) marking my App component as not assignable to variable type Component, but it doesn't :(

I think the problem may be in my configs (I just used information from the official sites, I'm not very good at this).

But I noticed the following:

UDP

I want to note that the code in index.tsx and App.tsx worked in default Vite templates and i'm pretty sure that this code is not the problem.

UDP 2

snnsnn pointed out a stupid mistake (Index.tsx changed) in the render method, but a new problem Argument type () => JSX.Element is not assignable to parameter type () => JSX.Element is a something more strange

App.tsx

import { Component, createSignal } from "solid-js";

const App: Component = () => {
  const [count, setCount] = createSignal<number>(0);
  return (
    <>
      <h1>Hello Stack Overflow {count()} times</h1>
      <button
        onClick={() => {
          setCount(count() + 1);
        }}
      >
        Say hello again
      </button>
    </>
  );
};

export default App;

index.tsx

import { render } from "solid-js/web";
import App from "./App";

render(() => <App />, document.querySelector("#root"));

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

.eslintrc.json

{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:solid/typescript"
  ],
  "overrides": [
  ],
  "parser": "@typescript-eslint/parser",
  "plugins": [
    "solid"
  ],
  "ignorePatterns": [
    "webpack.config.js"
  ],
  "rules": {
  }
}

.babelrc

{
  "presets": [
    "solid",
    "@babel/preset-env",
    "@babel/preset-typescript"
  ]
}

package.json

{
  "name": "solid-webpack-test",
  "version": "0.0.0",
  "description": "",
  "scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "solid-js": "^1.7.3"
  },
  "devDependencies": {
    "@babel/core": "^7.21.4",
    "@babel/eslint-parser": "^7.21.3",
    "@babel/preset-env": "^7.21.4",
    "@babel/preset-typescript": "^7.21.4",
    "@typescript-eslint/eslint-plugin": "^5.59.1",
    "@typescript-eslint/parser": "^5.59.1",
    "babel-loader": "^9.1.2",
    "babel-preset-solid": "^1.7.3",
    "eslint": "^8.39.0",
    "eslint-plugin-solid": "~0.12.1",
    "html-webpack-plugin": "^5.5.1",
    "prettier": "^2.8.8",
    "typescript": "^5.0.4",
    "webpack": "^5.80.0",
    "webpack-cli": "^5.0.2",
    "webpack-dev-server": "^4.13.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "jsxImportSource": "solid-js"
  },
  "include": [
    "src"
  ],
  "exclude": ["node_modules"]
}

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const config = {
  entry: "./src/index.tsx",
  output: {
    path: path.join(__dirname, "dist"),
    filename: "bundle.js",
  },
  devServer: {
    static: path.join(__dirname, "dist"),
    devMiddleware: {
      publicPath: "/",
    },
    port: 3000,
  },
  mode: "development",
  resolve: {
    extensions: [".tsx", ".ts", ".js", ".json"],
  },
  module: {
    rules: [
      {
        test: /\.(ts)x?$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
};

module.exports = config;

Solution

  • The render function expects you to pass JSX element, not a component, so you need to either remove :Component type and let typesript derive the type or replace it withApp: () => JSXElement.

    import { render } from 'solid-js/web';
    import { JSXElement } from 'solid-js';
    
    const App: () => JSXElement = () => {
      return <div>Hello World</div>;
    };
    
    render(() => <App />, document.querySelector('root')!);
    

    The alternate form is also OK:

    render(App, document.querySelector('root')!);
    

    https://www.solidjs.com/docs/latest#render

    Also Component type is not same as returning a JSX element, because the latter does not accept any parameters. Component is not same as () => JSXElement.