将Javascript迁移到Typescript React组件时出现问题

dluptydi  于 2023-03-19  发布在  TypeScript
关注(0)|答案(2)|浏览(126)

我的项目中的TypeScript配置当前存在问题。
首先,我使用常规JavaScript开发了我的应用程序。然后,为了学习TypeScript,我将我的JavaScript项目转换为TypeScript项目。
为此,我运行了一个yarn add typescript命令,并添加了Node.js、React、React-DOM和React-Router-DOM所需的类型。
我目前正在使用:

  • React性JS:v18.2.0
  • 维生素JS:4.2.0
  • 类型脚本:版本5.0.2

这是我运行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",
            },
        },
    },
});

如果我尝试使用类型:
index.ts

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

这是我的致命错误:

[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>);

我的项目是完美的运行,如果我不使用任何东西的 typescript 。

6jygbczu

6jygbczu1#

我认为这里的根本问题是document.getElementById可以返回HTMLElementnull,因此,当您尝试将其传递给createRoot方法时,typescript引发错误。它引发此错误是因为createRoot方法接受HTMLElement类型而不是null类型。编译器告诉您,在尝试使用document.getElementById之前,需要确保它的返回值不是null
为了减少此错误,您正在尝试将getElementById的返回类型Assert为HTMLElement。由于您是在函数括号内执行此操作,因此会出现语法错误。
要解决这个问题,正确的方法是,在尝试使用document.getElementById之前,您应该检查以确保从document.getElementById返回的值有值(类似这样的事情是使用打字脚本的许多原因之一):

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
}

这样,您就不会强迫编译器忽略某些内容,并且实际上拥有了类型安全代码。
另一方面,如果你10000%确定它不会返回null,你可以通过使用as关键字来缩小类型,你只需要以一种不会抛出语法错误的方式来分组:

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

注意,在这个示例中使用as关键字基本上是强制typescript像javascript一样工作,您应该使用IMHO上面的第一个方法。

dy1byipe

dy1byipe2#

Vite配置似乎没有正确设置为处理TypeScript文件。请更新您的vite.config.ts文件,以包含用于esbuild的TypeScript加载程序和适当的文件扩展名。以下是修改后的vite.config.ts文件:

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",
            },
        },
    },
});

此配置将默认esbuild加载程序设置为“tsx”,并添加一个regex模式以包括TypeScript(.ts)和带JSX(.tsx)的TypeScript文件。
另外,在tsconfig.json文件中有一个语法错误。在“jsx”中有一个额外的尾随逗号:“react-jsx”行。删除逗号,它应该如下所示:

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

更新Vite配置并修复tsconfig.json中的语法错误后,您的项目现在应该可以正确使用TypeScript。

相关问题