typescriptreact-nativerequireexpo

Getting "Invalid call" when using require with Typescript and Expo


I am trying to play some audio in a react-native app created with the expo-cli.

The code is written in typescript and the offending code looks like this, taken from the 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!
          }
          
    }
[...]
}

When the app loads, it gives the following error, even before it gets to the screen with the sound

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

I realize that the code example is with javascript and not typescript, but what am I missing?

My tsconfig.json is the one from the expo typescript example and looks like this

{
  "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 because 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"
  ]
}

Solution

  • I got help via Twitter, and the problem is that require() does not work with dynamic values. This also explains why the errors happened before the app was even loaded, as it tried to resolve the require at build or load time and not at runtime as I had thought.