You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React懒加载引入时遭遇TS2349错误的解决求助

React 18 + TypeScript 动态导入默认导出函数报错解决方法

我正尝试按照React官方文档描述,在React 18项目中用动态import()语法做代码分割,实现懒加载。官方文档提到:

为应用引入代码分割的最佳方式是使用动态import()语法。

原始可运行代码

import addMobileAppStartupListeners from './components/listeners/addMobileAppStartupListeners';

const startApp = () => {
  if (isPlatformMobile()) {
   addMobileAppStartupListeners();
  }
  startAccessibilityTestingIfDebug();
};

addMobileAppStartupListeners.tsx代码:

const addMobileAppStartupListeners = () => {
  document.addEventListener(
    'deviceready',
    () => {
      // 点击通知时触发的方法
      PluginPushNotifactions.addListener(
        'pushNotificationActionPerformed',
        (notification: PluginActionPerformed) => {
          debugLog('push registration tapped', notification);
        },
      );
    },
    false,
  );
};

export default addMobileAppStartupListeners;

尝试动态导入后的报错

因为是默认导出,我尝试用动态导入改写代码:

const startApp = () => {
  if (isPlatformMobile()) {
    import('./components/listeners/addMobileAppStartupListeners').then(
      (addMobileAppStartupListeners) => {
        addMobileAppStartupListeners();
      },
    );
  }
  startAccessibilityTestingIfDebug();
};

但TypeScript抛出报错:

[react-scripts] ERROR in src/index.tsx:41:9
[react-scripts] TS2349: This expression is not callable.
[react-scripts]   Type 'typeof import("/Users/private/d/ionic/src/components/listeners/addMobileAppStartupListeners")' has no call signatures.

我TypeScript基础薄弱,推测需要给导入的函数指定类型,但不知道具体操作方法。

环境详情

TypeScript 4.9.5

{
  "compilerOptions": {
    "target": "es2017",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "noFallthroughCasesInSwitch": true
  },
  // 配置文件
  "files": [
    "capacitor.config.ts",
    "ionic.config.json",
    "lingui.config.ts"
  ],
  "include": [
    "src",
    "tests/playwright"
  ]
}

问题原因

动态import()返回的是模块对象,默认导出的内容会挂载在这个对象的default属性上。你直接调用模块对象自然会报错——模块本身不是可调用的函数。

修复方法

有三种简单的修复方式:

方式1:解构获取default导出

在then回调里解构出default属性,直接使用:

const startApp = () => {
  if (isPlatformMobile()) {
    import('./components/listeners/addMobileAppStartupListeners').then(
      ({ default: addMobileAppStartupListeners }) => {
        addMobileAppStartupListeners();
      },
    );
  }
  startAccessibilityTestingIfDebug();
};

方式2:直接调用模块的default属性

直接访问模块对象的default属性并调用:

const startApp = () => {
  if (isPlatformMobile()) {
    import('./components/listeners/addMobileAppStartupListeners').then(
      (module) => {
        module.default();
      },
    );
  }
  startAccessibilityTestingIfDebug();
};

方式3:用async/await简化代码

如果允许startApp变成异步函数,还可以用async/await让代码更简洁:

const startApp = async () => {
  if (isPlatformMobile()) {
    const { default: addMobileAppStartupListeners } = await import('./components/listeners/addMobileAppStartupListeners');
    addMobileAppStartupListeners();
  }
  startAccessibilityTestingIfDebug();
};

补充说明

静态导入时你用了import addMobileAppStartupListeners from '...',TypeScript(配合allowSyntheticDefaultImports配置)会自动帮你处理默认导出的映射,直接拿到函数本身;但动态import不会做这个自动映射,必须显式访问default属性。

内容的提问来源于stack exchange,提问作者Patrick Kenny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:55:43