将 require 与 Typescript 和 Expo 一起使用时出现“无效呼叫”

Posted

技术标签:

【中文标题】将 require 与 Typescript 和 Expo 一起使用时出现“无效呼叫”【英文标题】:Getting "Invalid call" when using require with Typescript and Expo 【发布时间】:2019-08-30 01:18:00 【问题描述】:

我正在尝试在使用 expo-cli 创建的 react-native 应用中播放一些音频。

代码是用打字稿写的,有问题的代码看起来像这样,取自expo.io documentation:

import * as React from 'react'
import  WorkoutComponent  from "./WorkoutExecutor";
import  Audio  from 'expo';

export default class AudioPlayer 

    private async playAudio(fileName: string) 
        console.log("Playing Audio: " + fileName);
        const soundFile = './assets/sounds/' + fileName + '.mp3';
        try 
            const  sound: soundObject, status  = await Audio.Sound.createAsync(
              require(soundFile),
               shouldPlay: true 
            );
            // Your sound is playing!
           catch (error) 
              console.log(error);
            // An error occurred!
          

    
[...]

当应用加载时,它会给出以下错误,甚至在它带着声音进入屏幕之前

[...]\src\AudioPlayer.ts:Invalid call at line 13: require(soundFile)

我意识到 coe 示例是使用 javascript 而不是 typescript,但我缺少什么?

我的 tsconfig.json 是 expo typescript 示例中的一个,看起来像这样


  "compilerOptions": 
    "baseUrl": "./src",
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "importHelpers": true,
    "jsx": "react-native",
    "module": "es2015",
    "moduleResolution": "node",
    "noEmitHelpers": true,
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    // Using the type definitions in @types/expo becuase they are still better than the ones provided by expo. See SvgScreen.tsx and SystemFontsScreen.tsx.
    "paths": 
      "expo": [
        "../node_modules/@types/expo",
        "../node_modules/expo"
      ],
    ,
    "skipLibCheck": true,
    "strict": true,
    "target": "es2017"
  ,
  "exclude": [
    "node_modules"
  ]

【问题讨论】:

【参考方案1】:

我通过 Twitter 获得了帮助,但问题是 require() 不适用于动态值。这也解释了为什么在应用加载之前就发生了错误,因为它试图在构建或加载时解决require,而不是像我想象的那样在运行时解决。

【讨论】:

这解释了错误。你有解决办法吗?【参考方案2】:
import * as React from 'react'
import  WorkoutComponent  from "./WorkoutExecutor";
import  Audio  from 'expo';

const fileA = require('path/to/sound/file.mp3');
const fileB = require('path/to/sound/file2.mp3');

export default class AudioPlayer 

    private async playAudio(fileName: string) 
       if (fileName == 'A') 
           var soundFile = fileA;
        else 
           var soundFile = fileB;
       
       try 
          const  sound: soundObject, status  = await Audio.Sound.createAsync(
          soundFile,
           shouldPlay: true 
        );
        // Your sound is playing!
       catch (error) 
          console.log(error);
        // An error occurred!
      


[...]

【讨论】:

【参考方案3】:

我通过使用修复它

import song from "./path_to_song/song.mp3"

【讨论】:

但这仅适用于应用启动时已知的静态值。我的问题是我试图加载一个我不知道应用程序加载文件名的文件。我最终使用了不同的方法来加载文件。

以上是关于将 require 与 Typescript 和 Expo 一起使用时出现“无效呼叫”的主要内容,如果未能解决你的问题,请参考以下文章

Mailchimp 和 Node.js 与 typescript noob 问题:Import vs Require

将 Typescript 的 baseUrl 编译器选项与节点一起使用

TypeScript var 与导入

TypeScript 中是不是有相当于 require().default 的东西?

将 typescript 定义文件与 nodejs 混合需要内部模块中的多个文件

错误 [ERR_REQUIRE_ESM]:ES 模块的 require() - Vue 3 Typescript