Search code examples
typescriptreact-nativeexpounion-typesexpo-av

Error trying to access the error property of AVPlaybackStatus


I'm new to TypeScript and am trying to work with expo-av for audio playback.

The following code gives me an error: TS2339: Property 'error' does not exist on type 'AVPlaybackStatus'.

const { sound, status } = await Audio.Sound.createAsync(track.mp3);
if (status.isLoaded) {
  console.info(status.durationMillis);
}
else {
  console.error("track not loaded", status.error);
}

I looked at the definition of status and found:

export type AVPlaybackStatus =
  | {
      isLoaded: false;
      androidImplementation?: string;
      error?: string; // populated exactly once when an error forces the object to unload
    }
  | {
      isLoaded: true;
      androidImplementation?: string;

      uri: string;

      progressUpdateIntervalMillis: number;
      durationMillis?: number;
      positionMillis: number;
      playableDurationMillis?: number;
      seekMillisToleranceBefore?: number;
      seekMillisToleranceAfter?: number;

      shouldPlay: boolean;
      isPlaying: boolean;
      isBuffering: boolean;

      rate: number;
      shouldCorrectPitch: boolean;
      volume: number;
      isMuted: boolean;
      isLooping: boolean;

      didJustFinish: boolean; // true exactly once when the track plays to finish
    };

I have never seen this construct before but am guessing this is a union or intersection type (?).

How do I access status.error? And what is the typical idiom / construct to work with such types?


Solution

  • The pattern is the discriminating union (docs), where TypeScript can exactly determine the type based on one field which is distinct for each of the alternatives. In this case it's the isLoaded boolean field, but for that to work, you do need to have strictNullChecks enabled. Other than that the way you're handling it is completely fine.