skip to Main Content

I am currently having issues with TypeScript configuration in my project.

Firstly, I developed my application using regular JavaScript. Then, wanting to learn TypeScript, I converted my JavaScript project into a TypeScript project.

To do this, I ran a yarn add typescript command and added the required types for Node.js, React, React-DOM, and React-Router-DOM.

I am currently using:

  • React.JS: v18.2.0
  • Vite.JS: 4.2.0
  • TypeScript: v5.0.2

There is my configuration files for running typescript:

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
  },
  "include": ["src/**/*"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

tsconfg.node.json

{
  "compilerOptions": {
    "composite": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}

vite.config.ts

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
    plugins: [react({
        include: '**/*.tsx'
    })],
    server: {
        port: 3000
    },
    esbuild: {
        loader: "jsx",
    },
    optimizeDeps: {
        esbuildOptions: {
            loader: {
                ".js": "jsx",
                ".ts": "tsx",
            },
        },
    },
});

If i try using types :

index.ts

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);

There is my vite error:

[plugin:vite:esbuild] Transform failed with 1 error:
/var/www/remote/dashboard/src/index.ts:25:65: ERROR: Expected ")" but found "as"
/var/www/remote/dashboard/src/index.ts:25:65
Expected ")" but found "as"
23 |  
24 |  
25 |  const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
   |                                                                   ^
26 |  
27 |  root.render(<RecoilRoot><App /></RecoilRoot>);

My project is running perfectly if i not use any thing of typescript.

2

Answers


  1. I think the underlying problem here is that document.getElementById can return either an HTMLElement or null. Because of this, when you try and pass it into the createRoot method, typescript throws an error. It is throwing this error because the createRoot method takes in an HTMLElement type but not a null type. The compiler is telling you that you need to make sure the return of document.getElementById is not null before you try and use it.

    To mitigate this error you are attempting to assert the return type of getElementById to an HTMLElement. Since you are doing so inside of the function parenthesis you are getting a syntax error.

    To fix this, the correct way, you should check to make sure that the return from document.getElementById has a value before attempting to use it (things like this are one of the many reasons for typescript):

    const myElement = document.getElementById('root');
    
    if (myElement !== null) {
      const root = ReactDOM.createRoot(myElement);
      // do whatever with root
    } else {
      // do something if the element cannot be found
    }
    

    This way, you are not forcing the compiler to ignore something and you actually have typesafe code.

    On the other hand, if you are 10000% sure this will never return null, you can narrow the type by casting with the as keyword. You just need to group it in a way that does not throw a syntax error:

    const myElement = document.getElementById('root') as HTMLElement;
    const root = ReactDOM.createRoot(myElement);
    

    Note that using the as keyword in this instance is basically forcing typescript to act like javascript. You should use the first method above IMHO.

    Login or Signup to reply.
  2. It appears that the Vite configuration is not properly set up to handle TypeScript files. Please update your vite.config.ts file to include the TypeScript loader for esbuild and the appropriate file extensions. Here’s the modified vite.config.ts file:

    import { defineConfig } from "vite";
    import react from "@vitejs/plugin-react";
    
    export default defineConfig({
        plugins: [react()],
        server: {
            port: 3000
        },
        esbuild: {
            loader: "tsx",
            include: /.tsx?$/,
        },
        optimizeDeps: {
            esbuildOptions: {
                loader: {
                    ".js": "jsx",
                    ".ts": "tsx",
                },
            },
        },
    });
    

    This configuration sets the default esbuild loader to "tsx" and adds a regex pattern to include both TypeScript (.ts) and TypeScript with JSX (.tsx) files.

    Additionally, there is a syntax error in your tsconfig.json file. You have an extra trailing comma in the "jsx": "react-jsx" line. Remove the comma, and it should look like this:

    {
      "compilerOptions": {
        ...
        "jsx": "react-jsx"
      },
      ...
    }
    

    After updating your Vite configuration and fixing the syntax error in tsconfig.json, your project should now work correctly with TypeScript.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search