TypeError: Super expression must be null or a func

2020-07-02 08:58发布

问题:

I'm currently trying to make multiple-files inheritance in ES6, with node.JS and Babel (I'm using Babel to convert the code from ES6 to ES5 'cause Node don't implement ES6 right now). I'm using import/export to "link" the differents files.

Actually I have : Parent Class (File 1)

export class Point
{
    constructor(x, y)
    {
        this.x = x;
        this.y = y;
    }

    toString() {
        return '(' + this.x + ', ' + this.y + ')';
    }
}

And : Child Class (File 2)

import Point from './pointES5'

export class ColorPoint extends Point
{
    constructor(x, y, color)
    {
        super(x, y);
        this.color = color;
    }

    toString() {
        return super.toString() + ' in ' + this.color;
    }
}

And the main Main (File 3)

import Point from './pointES5'
import ColorPoint from './colorpointES5'

var m_point = new Point();
var m_colorpoint = new ColorPoint();

console.log(m_point.toString());
console.log(m_colorpoint.toString());

I'm doin' that to test the toString() methods calls, from Parent and from Child.
So then I use Babel to convert the code from ES6 to ES5 and I run each parts separately to test if it's ok or not.
- Point (the Parent) is good, and execute without error.
- ColorPoint (the Child) don't run completely and throw :

TypeError: Super expression must either be null or a function, not undefined

The first line of the StackTrace is :

function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.proto = superClass; } (It comes from the ES5 converted code (Babelified), and I can post it entirely if it's needed).

It is frustrating cause this code is very simple... But I don't see what is causing the error.

I try differents versions of Babel (5, 5.8, 6) but there is no differences...

What have I done wrong ?

PS : I forgot to tell : it WORKS PERFECTLY when I do that in just one file. But it's really important to me to have only one class by file...

回答1:

Your export doesn't match your import:

export class Point
// and
import Point from './pointES5'

You're exporting a named symbol but importing the default, so you'll be getting the wrong object as Point in your second file.

You can either use:

export default class Point

in the first class file or

import {Point} from './pointES5';

in the second file to fetch the right reference. If you're going for the single-class-per-file layout, I'd suggest the former. You'll typically only have a single class being exported, so it makes sense to have that as the default.

What you have now is the equivalent of:

// in Point
module.exports = {
  Point: Point
};

// in ColorPoint
var Point = require('./pointES5'); // will point to *the whole object*

class SubPoint extends Point


回答2:

It could also be a problem in your webpack config, if you are using webpack as a bundler. Or how you uglify your code. for example how I solved my specific issue with the NPM package react-draft-wysiwyg and the wepback plugin uglifyjs-webpack-plugin.

What worked for me here was to set the inline option for the compress option to false because by default it is true for the uglifyOptions.

optimization:{
  minimizer: [new UglifyJsPlugin({
  uglifyOptions: {
    compress: {
      inline: 1, // this right here
      // keep_fnames: true
    },
    mangle: {
      // keep_fnames: true
    }
  }
})]
}