Livecoding: You Can’t Extend an Object

DZone 's Guide to

Livecoding: You Can’t Extend an Object

A DZone MVB tries to tackle of extending an object using the JavaScript framework, React. Read and watch to see who he handles it!

· Web Dev Zone ·
Free Resource

Today we battled with a fearsome error, an error of odd implications and no clear solutions. Uncaught TypeError: Super expression must either be null or function

What does that even mean!?

Well, it means that when you import TransitionableComponent from 'react-transitionable-component', you get an object instead of a function. We confirmed the problem with some console.log calls. After importing TransitionableComponent as an object.

It's an object!

It looks just like a React component is supposed to. There’s a constructor method, a bunch of default object methods, and – I assume – all the Component methods as well. That’s great when you want to use a component in your render() function. Not so great when you want to use it as a parent class.

When you do something like class Arc extends TransitionableComponent, it fails. You can extend a null or a function, but not an object.

You can inherit from a class, but not from an instance of a class. I’m sure it’s like that in every language, but the reason it’s like that in JavaScript is that class TransitionableComponent extends Component transpiles into:

var TransitionableComponent = function (_Component) {
        _inherits(TransitionableComponent, _Component);

        function TransitionableComponent(props) {
            _classCallCheck(this, TransitionableComponent);

                    // I think this is super(props)
            var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(TransitionableComponent).call(this, props));

            // this is where your constructor body goes
            return _this;

        _createClass(TransitionableComponent, [{
           // this is where your class body goes

        return TransitionableComponent;

That _inherits call is the crucial piece. It does a bunch of .prototype magic to extend the definition of a given class with the definition of a child class. Instances don’t have prototypes, functions do.

Functions have a prototype property because of legacy reasons, I’m sure. That’s how JavaScript has always understood the concept of classes – generator/constructor functions double as classes.

At this point, TransitionableComponent is a function – just like we’d expect. With some console.log-ing we confirmed that it remains a function right up until the point where we import it in our sample project.


I don’t know why it becomes an object. Our guessing and prodding didn’t reveal much. This is what importing transpiles to:

var _TransitionableComponent = __webpack_require__(16);

var _TransitionableComponent2 = _interopRequireDefault(_TransitionableComponent);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

This code might return an object if you’re importing something that isn’t an ES6 Module. But we know that’s not our problem because TransitionableComponent.default is undefined.

You’d think __webpack_require__ was instantiating our component and returning an object instead of a function, but it works correctly when you import React’s default Component. Curiously, React’s compiled code looks like normal ES5 without even a hint of Webpack or Babel.


I am at a loss. I have no idea what’s going on or why. But until we figure this out, react-transitionable-component will not be a usable library and my chance at open-source glory lays trampled in the wastelands of npmjs.com.

javascript ,react ,web dev

Published at DZone with permission of Swizec Teller , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}