Typescript Box 生成的联合类型过于复杂而无法表示

Viv*_*ere 7 three.js typescript reactjs material-ui react-typescript

渲染 aBox会产生以下错误:

表达式生成的联合类型太复杂而无法表示。ts(2590)

正如我在这里看到的,这是因为同时安装了@mui/material@react-three/drei& @react-three/fiber

这个错误背后的原因是什么?我只Box从 导入组件mui。是否存在类型混淆或其他问题?解决方案/解决方法是什么?

重现步骤:

  1. 设置 cra 应用程序:npx create-react-app my-app --template typescript
  2. 将以下包添加到您的package.json
  "dependencies": {
    "@azure/msal-browser": "^2.18.0",
    "@azure/msal-react": "^1.1.0",
    "@emotion/react": "^11.5.0",
    "@emotion/styled": "^11.3.0",
    "@mui/icons-material": "^5.0.4",
    "@mui/lab": "^5.0.0-alpha.51",
    "@mui/material": "^5.0.4",
    "@mui/system": "^5.0.4",
    "@react-three/drei": "^7.16.8",
    "@react-three/fiber": "^7.0.17",
    "axios": "^0.23.0",
    "dotenv": "^10.0.0",
    "localforage": "^1.10.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router": "^5.2.1",
    "react-router-dom": "^5.3.0",
    "react-scripts": "4.0.3",
    "three": "^0.133.1",
    "three-stdlib": "^2.5.4",
    "web-vitals": "^1.1.2",
    "zustand": "^3.5.14"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "@types/jest": "^26.0.24",
    "@types/node": "^12.20.33",
    "@types/react": "^17.0.30",
    "@types/react-dom": "^17.0.9",
    "@types/react-router-dom": "^5.3.1",
    "@types/three": "^0.133.1",
    "@typescript-eslint/eslint-plugin": "^4.29.3",
    "@typescript-eslint/parser": "^4.29.3",
    "cross-env": "^7.0.3",
    "eslint-config-airbnb": "^18.2.1",
    "eslint-config-airbnb-typescript": "^14.0.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-import": "^2.25.2",
    "eslint-plugin-jsx-a11y": "^6.4.1",
    "eslint-plugin-react": "^7.26.1",
    "eslint-plugin-react-hooks": "^4.2.0",
    "jest-when": "^3.4.1",
    "rimraf": "^3.0.2",
    "typescript": "^4.4.4"
  },
Run Code Online (Sandbox Code Playgroud)
  1. 跑步npm install
  2. 确保您正在运行Typescript v4.4.4
  3. 将以下组件添加到您的src. 我把它命名为ThreeRenderer.tsx
import { Html, OrbitControls, PerspectiveCamera, useGLTF, useProgress } from '@react-three/drei';
import { Canvas, useFrame } from '@react-three/fiber';
import { FC, Suspense, useEffect, useRef, useState } from 'react';
import { AnimationAction, AnimationMixer } from 'three';
import { GLTF, GLTFLoader } from 'three-stdlib';
import create from 'zustand';
import { devtools } from 'zustand/middleware';

export const useGLTFModel = create<{ readonly model: () => GLTF | undefined }>(
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  devtools((set) => ({
    model: () => undefined
  }))
);

export const useGLTFAnimationAction = create<{ readonly animationAction: () => AnimationAction[] | undefined }>(
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  devtools((set) => ({
    animationAction: () => undefined
  }))
);

interface ModelProps {
  readonly gltfPath: string;
  readonly onLoad: () => void;
}

const Model: FC<ModelProps> = ({ gltfPath, onLoad }) => {
  const model = useGLTF(gltfPath, undefined, undefined, (loader: GLTFLoader) => {
    loader.manager.onLoad = onLoad;
  });

  // Refs
  const rootRef = useRef();
  const animationActionsRef = useRef<AnimationAction[]>();

  // Mixer
  const [mixer] = useState(() => new AnimationMixer(model.scene));
  useFrame((_state, delta) => mixer.update(delta));

  // Effects
  useEffect(() => {
    useGLTFModel.setState({ model: () => model });

    animationActionsRef.current = model.animations.map((animation) => mixer.clipAction(animation, rootRef.current));
    useGLTFAnimationAction.setState({ animationAction: () => animationActionsRef.current });

    return () => {
      model.animations.map((animation) => mixer.uncacheClip(animation));
    };
  }, [model, mixer]);

  return <primitive ref={rootRef.current} object={model.scene} />;
};

const Progress = () => {
  const { progress } = useProgress();
  return (
    <Html center>
      <span style={{ color: 'white' }}>{progress}% loaded</span>
    </Html>
  );
};

const ThreeRenderer: FC<ModelProps> = ({ gltfPath, onLoad }): JSX.Element => {
  const cameraRef = useRef();

  return (
    <Canvas>
      <PerspectiveCamera ref={cameraRef} position={[0, 5, 5]} />
      <OrbitControls camera={cameraRef.current} />
      <ambientLight intensity={0.5} />
      <Suspense fallback={<Progress />}>
        {/* <Environment preset="city" /> */}
        <Model gltfPath={gltfPath} onLoad={onLoad} />
      </Suspense>
    </Canvas>
  );
};

export default ThreeRenderer;

Run Code Online (Sandbox Code Playgroud)
  1. 转到App.tsx并添加一个Box组件@mui/material
import React from 'react';
import logo from './logo.svg';
import './App.css';
import {Box} from '@mui/material';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        <Box>

        </Box>
      </header>
    </div>
  );
}

export default App;

Run Code Online (Sandbox Code Playgroud)
  1. 您应该会看到错误出现。我所看到的: 在此输入图像描述

注意 请尝试在本地VSCode或您首选的编辑器中重现此错误。codesandbox例如,我没有设法重现这一点。我不知道为什么没有出现该问题。我怀疑这是因为他们使用不同的打字稿版本。

更新

我在 MUI 和 React-3 上都提出了问题:

Dib*_*hra 7

  1. 在 VS Code 中打开 JavaScript 或 TypeScript 文件。
  2. 在 VS Code 命令面板中,运行 TypeScript: Select TypeScript version command
  3. 确保您已选择“使用工作区版本”。

帖子来源:FreePhoenix888

原答案:这里


oBu*_*usk 4

虽然我确信在某些情况下可能会发生此问题,但现在发生在我身上的原因是,安装了定义了类型声明的npm重复版本@chakra-ui/systemforwardRef().

\n

当我跑步时,npm ls @chakra-ui/system我可以看到我同时拥有@chakra-ui/system@1.9.1@chakra-ui/system@1.9.0

\n

这可能是因为某些依赖项(例如@chakra-ui/skeleton@1.2.4定义了 的精确版本)1.9.0@chakra-ui/system而大多数包(例如@chakra-ui/menu@1.8.3)将非常开放的版本定义>=1.0.0peerDependencies. 从npm v7peerDependencies开始,npm默认安装。

\n

看起来这可能会导致 npm 安装最新版本的开放版本>=1.0.0,然后1.9.0单独安装特定版本,并且不够智能来删除重复数据。

\n

我可以通过以下任一方式解决这个问题

\n
    \n
  • rm package-lock.json && npm install --legacy-peer-deps。然而,这对 npm 安装的软件包有很大影响。

    \n
  • \n
  • 或者,向 中添加overrides(requires npm >=8.3) 以package.json指定要安装的特定版本。

    \n
    "overrides": {\n     "@chakra-ui/system": "1.9.1"\n }\n
    Run Code Online (Sandbox Code Playgroud)\n

    您可能必须package-lock.json在再次运行安装之前删除它来重新生成,以实际强制执行此新解决方案。

    \n

    这只会确保对特定包进行重复数据删除,而不会像 \xc2\xb4--legacy-peer-deps` 那样更改其他不相关的包。

    \n
  • \n
\n