28
votes
interface Window {
    AudioContext: AudioContext;
    webkitAudioContext: Function
}

let contextClass = window.AudioContext || window.webkitAudioContext;
let context: AudioContext = new contextClass();

The last line is giving me this error,

Cannot use 'new' with an expression whose type lacks a call or construct signature

How can I resolve this?

3

3 Answers

31
votes

The problem is that the compiler treats the contextClass variable as an instance of AudioContext while in fact it's merely a constructor function for an AudioContext.

You can simply use any and the compiler will let you new it:

let contextClass : any = window.AudioContext || window.webkitAudioContext;
let context: AudioContext = new contextClass();

Another option would be to introduce a Constructable<T> interface that will let you new up those types:

interface Constructable<T> {
    new(...args: any) : T;
}

interface Window
{
    AudioContext: Constructable<AudioContext>;
    webkitAudioContext: Constructable<AudioContext>
}

let contextClass = window.AudioContext || window.webkitAudioContext;
let context: AudioContext = new contextClass();
10
votes

You can't new up an instance. new instanceofAudioContext() isn't a valid thing to do.

Your interface doesn't match the API you're trying to use. In the browser, window.AudioContext isn't a instance of AudioContext. It's the class definition method, typeof AudioContext. You'll also have the same problem with the Function.

If you'd still like to keep your interface. Try this

interface Window {
    AudioContext: typeof AudioContext;
    webkitAudioContext: typeof AudioContext
}

declare var window: Window;

var AudioContextDecl = window.AudioContext || window.webkitAudioContext;
var audioCtx = new AudioContext();

Or if you don't want the interface,

var AudioContextDecl = <typeof AudioContext>(window.AudioContext || window.webkitAudioContext);
var audioCtx = new AudioContext();

Or even just use any. It all transpiles to the same thing.

0
votes

Try typeof here

declare global {
    interface Window {
        AudioContext: typeof AudioContext;
        webkitAudioContext: Function;
    }
}

let contextClass = window.AudioContext || window.webkitAudioContext;
let context: AudioContext = new contextClass();