简体   繁体   中英

Typescript: undefined is not a constructor

I have a clone function that I'm testing with Mocha/Chai:

export function clone(source: any): any {
    let output = {};
    if (isObject(source)) {
        (<any>Object).keys(source).forEach(key => {
            (<any>Object).assign(output, { [key]: source[key] });
        });
    }
    return output;
}

Here's the test:

let obj = {
    a: [
        {
            a: 3,
            b: 5,
            c: [6, 8]
        }
    ]
};

it('clone(object) creates deep clone', () => {
    let cloned = ObjectHelper.clone(obj);

    expect(cloned.a[0].a).to.equal(3);
    expect(cloned.a[0].c[1]).to.equal(6);
});

But I get this error:

undefined is not a constructor (evaluating 'Object.assign(output, (_a = {}, _a[key] = source[key], _a))')

This only fails in the tests, not in the browser.

Karma config:

module.exports = function(config) {
    config.set({
        /*
         * Enable or disable watching files and executing the tests whenever
         * one of the files in the 'files' field is changed.
         */
        autoWatch: true,

        /*
         * The root path location that will be used to resolve all relative
         * paths defined in 'files' and 'exclude'.
         */
        basePath: '',

        /*
         * List of browsers to launch and capture tests in. In order to use a
         * specified browser, you must npm install the corresponding
         * karma-***-launcher.
         * http://karma-runner.github.io/0.13/config/browsers.html
         */
        browsers: ['PhantomJS'],

        // Enable or disable colors in the output (reporters and logs)
        colors: true,

        // List of files/patterns to exclude from loaded files
        exclude: [],

        /*
         * The files array determines which files are included in the browser
         * and which files are watched and served by Karma. The order of patterns
         * determines the order in which files are included in the browser.
         * http://karma-runner.github.io/0.13/config/files.html
         */
        files: [
            'src/**/*.spec.ts'
        ],

        /*
         * List of test frameworks you want to use. For example, if you want to
         * use mocha, chai, and sinon, you'll need to npm install their
         * corresponding karma-*** modules and include them in the list of plugins
         * as well as below.
         */
        frameworks: ['mocha', 'chai', 'sinon'],

        logLevel: config.LOG_INFO,

        /*
         * By default, Karma loads all sibling NPM modules which have a name
         * starting with karma-*. You can also explicitly list plugins you want
         * to load via the plugins configuration setting.
         */
        plugins: [
            'karma-*'
        ],

        // The port where the Karma web server will be listening.
        port: 9876,

        /*
         * A map of preprocessors to use. Requires the corresponding karma-*
         * npm module to be npm installed and added to the 'plugins' field.
         */
        preprocessors: {
            'src/**/*.spec.ts': ['webpack']
        },

        /*
         * A list of reporters to use to display the test results. In order to
         * use the karma-mocha-reporter, you must npm install the module and
         * include it in the list of plugins.
         */
        reporters: ['mocha'],

        /*
         * If true, Karma will start and capture all configured browsers, run
         * tests and then exit with an exit code of 0 or 1 depending on whether
         * all tests passed or any tests failed.
         */
        singleRun: false,

        /*
         * This field is necessary because we are using webpack as a preprocessor.
         * You will need to specify the webpack configuration (although in this
         * case, we are simply leveraging the existing webpack.config.js file).
         *
         * If you have a different webpack.config.js file that's used for testing
         * purposes, you can specify that here.
         */
        webpack: {
            module: webpackConfig.module,
            resolve: webpackConfig.resolve
        }
    });
};

I think that your problem is that your environment does not have Object.create implemented, that is you don't have ES6 features.

Here's a polyfil for PhantomJs: https://www.npmjs.com/package/phantomjs-polyfill-object-assign

Also, you can polyfil it in typescript (just so you won't have to cast it to any ):

interface ObjectConstructor {
    keys(o: any): string[];
    assign(target: any, ...sources: any[]): any;
}

If you use ES6 as the target for your compiler then you won't need this polyfil as it's already built in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM