title: Using typescript/web audio api on ios
body: <p>I'm working on a web site that will play audio files using the Web Audio API. I'm using typescript and Angular 2 in Visual Studio Code. I can get everything to work well on platforms other than ios; but on e.g. an iPad, I'm running into some baffling errors. </p>
  
  <p>The first problem is how to get an AudioContext that will work on both ios and non-ios platforms. I know it can be done in plain javascript, e.g. <a href="http://gopherwoodstudios.com/wa/mp3/test.htm" rel="nofollow noreferrer">http://gopherwoodstudios.com/wa/mp3/test.htm</a>. The need for a button press is annoying, but I can live with it. So I think the problem I'm having is related to typescript. (I'm a typescript newbie, so I could be misunderstanding some basics here.) </p>
  
  <p>On ios, what you get at runtime is still a webkitAudioContext, not an AudioContext. It seems that the typescript definitions I'm using don't understand how to deal with that. Either that or I don't know how to tell it what it needs to know. Originally I had a member variable of type AudioContext, and on non-ios platforms everything worked fine. To accommodate ios, I tried changing the variable's type to any, so that I could put in a webkitAudioContext if that exists and AudioContext doesn't; that code looks like this (this is all prototype code, so the error handling very provisional):</p>
  
  <pre><code>export class PlayerService {
  private static _audioContext: any = null;
  //......
  public static getAudioContext(): any {
    if (!PlayerService._audioContext) {
      try {
        if (typeof AudioContext !== "undefined") {
          // We have an AudioContext type, so use it.
          PlayerService._audioContext = new AudioContext();
        } else if (window['webkitAudioContext'] !== "undefined") {
          // We don't have AudioContext, but we do have webkitAudioContext,
          // so attempt to use that.
          PlayerService._audioContext = Object.create(window['webkitAudioContext'].prototype);
        } else {
          throw new Error('AudioContext not supported. :(');
        }
      } catch (err) {
        console.log(err.message);
        alert('Cannot create audio context.');
        throw err;
      }
    }
    return PlayerService._audioContext;
  } 
  </code></pre>
  
  <p>This still works on non-ios platforms; and on ios, it manages to return a webkitAudioContext, complete with the expected methods and properties. (The Object.create(...) was the only way I could find to get this much to work.) Later, though, when I call decodeAudioData on this object, I get an error that says </p>
  
  <pre><code>TypeError: Can only call AudioContext.decodeAudioData on instance of AudioContext.
  </code></pre>
  
  <p>Since the variable that it's trying to call the decodeAudioData method on is typed as 'any' rather than 'AudioContext', I don't know where it's getting the idea that it has to be an AudioContext. But in any case, this can't be the right way to approach the problem. I don't have type info anywhere about webkitAudioContext, only about AudioContext. Does the necessary type info exist somewhere and I just haven't found it? If it doesn't exist, would it be difficult to create it? Alternatively, is there a way to bypass the type checking altogether for this set of classes (not my preferred option, but if it's the best we can do for now, I'll take it)? Or is there some completely different way to approach this that I don't know about?</p>