7

For example, this is perfectly fine code. (The style is ES6)

import {List} from 'immutable';

console.log(List()); // List []

However, this fails.

class Foo {}

Foo(); // TypeError: Cannot call a class as a function

Further, this fails, too.

class Foo extends List {}

Foo(); // TypeError: Cannot call a class as a function
almostflan
  • 640
  • 4
  • 15
  • 1
    Probably because they're not constructed using `class`? Or the ES6 transpiler was in loose mode. – Bergi Sep 16 '15 at 21:54
  • In what environment are you executing this, which `immutable` version are you using? – Bergi Sep 16 '15 at 21:55
  • `immutable` version is 3.7.5 – almostflan Sep 16 '15 at 21:55
  • I think your call on the transpiler is probably where it's at. Will keep investigating and report back if I find anything :) – almostflan Sep 16 '15 at 21:56
  • I believe I've enabled loose mode, but to no avail. Seems to fail, like above. I'm using `babelify` 6.3.0 for transpiling (under the covers, it's `babel` 5.8.24). – almostflan Sep 16 '15 at 22:11
  • Looks related: http://stackoverflow.com/questions/30689817/es6-call-class-constructor-without-new-keyword – almostflan Sep 16 '15 at 22:19
  • 1
    Anyway, I'm going to stop investigating. I like the workaround provided here. http://stackoverflow.com/a/31789308/1438285 – almostflan Sep 16 '15 at 22:39
  • The answer didn't work for me. I think I'm resigned to "new" :( – almostflan Sep 16 '15 at 22:52
  • You mean the workaround does not work? What is the problem? – Bergi Sep 17 '15 at 12:56
  • I had issues with it when I extended `List`. I'm guessing it was related to the transpiling, but didn't investigate further. – almostflan Sep 18 '15 at 20:07
  • Ah, thanks for testing. Right, that's likely problematic, I edited my answer there. However, transpilers don't really support `Reflect` or `new.target`, so you have to ensure that you `extends List` before overwriting `List` with the new-less function. Or use `… extends _List`. – Bergi Sep 19 '15 at 10:32

1 Answers1

9

Looks like the magic for immutable happens in their custom addon to the transpiler here.

They're basically creating their own createClass which skips the check. This is a snippet from the transpiled (via babel) version of my code above.

var Foo = (function (_List) {
  _inherits(Foo, _List);

  function Foo() {
    _classCallCheck(this, Board);

    _get(Object.getPrototypeOf(Foo.prototype), 'constructor', this).apply(this, arguments);
  }

  return Foo;
})(_immutable.List);

Where _classCallCheck looks like this.

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError('Cannot call a class as a function');
    }
}

For immutable, it seems the ES6 code is first transformed to already include the createClass calls.

almostflan
  • 640
  • 4
  • 15