Search code examples
typescriptampersand

Typescript: Invalid 'new' expression


In an attempt to help this person out I was stubbing out the typescript definitions for the Ampersand.js library. Given the following typescript code, why does the compiler output an Invalid 'new' experession error?

[Here's a link to run the code using the typescript playground.]

declare module ampersand {
    interface AmpersandState {
        // todo...
    }

    interface AmpersandCollection {
        // todo...
    }

    interface ModelExtendOptions {
        parse?: boolean;
        parent?: AmpersandState;
        collection?: AmpersandCollection;
    }

    interface ModelSaveOptions {
        patch?: boolean;
    }

    class AmpersandModel<T> {
        constructor(attrs: T, options?: ModelExtendOptions);
        save: (attrs?: T, options?: ModelSaveOptions) => void;
        // todo:  fetch, destroy, sync, etc...
    }

    interface ExtendOptions {
        props?: {};
        session?: {};
        derived?: {};
    }   

    interface AmpersandModelStatic {
        extend: <T>(options: ExtendOptions) => AmpersandModel<T>;
    }
} 

declare var AmpersandModel: ampersand.AmpersandModelStatic;


interface PersonProps {
    firstName: string;
    lastName: string;
}

var Person = AmpersandModel.extend<PersonProps>({ props: { firstName: 'string', lastName: 'string' } });

var me = new Person({ firstName: 'Phil', lastName: 'Roberts' });

Invalid 'new' expression.


Solution

  • My extend method was returning an instance of AmpersandModel, not the ApersandModel's constructor function. Corrected code:

    declare module ampersand {
        interface AmpersandState {
            // todo...
        }
    
        interface AmpersandCollection {
            // todo...
        }
    
        interface ModelExtendOptions {
            parse?: boolean;
            parent?: AmpersandState;
            collection?: AmpersandCollection;
        }
    
        interface ModelSaveOptions {
            patch?: boolean;
        }
    
        interface AmpersandModel<T> {
            save: (attrs?: T, options?: ModelSaveOptions) => void;
            // todo:  fetch, destroy, sync, etc...
        }
    
        interface AmpersandModelConstructor<T> {
            new (attrs: T, options?: ModelExtendOptions): AmpersandModel<T>;
        }   
    
        interface ExtendOptions {
            props?: {};
            session?: {};
            derived?: {};
        }   
    
        interface AmpersandModelStatic {
            extend: <T>(options: ExtendOptions) => AmpersandModelConstructor<T>;
        }
    } 
    
    declare var AmpersandModel: ampersand.AmpersandModelStatic;
    
    interface PersonProps {
        firstName: string;
        lastName: string;
    }
    
    interface IPerson extends PersonProps, ampersand.AmpersandModel<PersonProps>{}
    
    var Person = AmpersandModel.extend<PersonProps>({ props: { firstName: 'string', lastName: 'string' } });
    
    var me = new Person({ firstName: 'Jeremy', lastName: 'Danyow' });