Typescript: tslib.__extends called on undefined prototype

Created on 19 Mar 2017  ·  15Comments  ·  Source: microsoft/TypeScript

TypeScript Version: 2.2.1

Code
To make things simple, here's a repo to easily reproduce this: https://github.com/jsayol/typescript-issue-14734

$ git clone https://github.com/jsayol/typescript-issue-14734.git
$ cd typescript-issue-14734
$ npm install
$ npm run build

And load index.html in the browser.

a.ts:
import { B } from './b';

export class A {
  constructor(public prop: string) {
  }

  b(): B {
    return new B(this.prop, 123);
  }

  log() {
    console.log(`Prop: ${this.prop}`);
  }
}
b.ts
import { A } from './a';

export class B extends A {
  constructor(prop: string, public otherStuff: number) {
    super(`B ${prop}`);
  }
}
index.ts
import { A } from './a';
import { B } from './b';

const a = new A('hello');
const b: B = a.b();
b.log();

Expected behavior:
Seeing "B hello" logged in the console.

For reference, putting all the code in a single file generates the correct output:

class A {
  constructor(public prop: string) {
  }

  b(): B {
    return new B(this.prop, 123);
  }

  log() {
    console.log(`Prop: ${this.prop}`);
  }
}

class B extends A {
  constructor(prop: string, public otherStuff: number) {
    super(`B ${prop}`);
  }
}

const a = new A('hello');
const b: B = a.b();
b.log();

Actual behavior:

tslib.es6.js:22 Uncaught TypeError: Object prototype may only be an Object or null: undefined
    at setPrototypeOf (<anonymous>)
    at Object.__extends [as a] (tslib.es6.js:22)
    at b.js:4
    at Object.__webpack_exports__.a (b.js:11)
    at __webpack_require__ (bootstrap 4672cf4…:19)
    at Object.defineProperty.value (bootstrap 4672cf4…:65)
    at __webpack_require__ (bootstrap 4672cf4…:19)
    at Object.<anonymous> (bundle.umd.js:108)
    at __webpack_require__ (bootstrap 4672cf4…:19)
    at Object.<anonymous> (bundle.umd.js:321)

This is the generated b.js, where the problem is:

import * as tslib_1 from "tslib";
import { A } from './a';
var B = (function (_super) {
    tslib_1.__extends(B, _super); // <--- Exception thrown here. "B" is undefined.
    function B(prop, otherStuff) {
        var _this = _super.call(this, "B " + prop) || this;
        _this.otherStuff = otherStuff;
        return _this;
    }
    return B;
}(A));
export { B };
//# sourceMappingURL=b.js.map
Question

Most helpful comment

You are dealing with a circular dependency. TypeScript can statically identify the shape of everything, therefore it is fine, but it seems WebPack (you module loader of choice) is not resolving the circular dependency effectively at runtime. I suspect that WebPack is attempting to instantiate module B before module A is ready, therefore module B can be loaded properly.

When they are in the same module, B isn't technically required by A until a certain method is called, therefore everything is resolved fine.

All 15 comments

Possibly related: #10837 and #5207

You are dealing with a circular dependency. TypeScript can statically identify the shape of everything, therefore it is fine, but it seems WebPack (you module loader of choice) is not resolving the circular dependency effectively at runtime. I suspect that WebPack is attempting to instantiate module B before module A is ready, therefore module B can be loaded properly.

When they are in the same module, B isn't technically required by A until a certain method is called, therefore everything is resolved fine.

Thanks @kitsonk, makes sense. I wasn't sure at first if this was a TypeScript or Webpack issue. I'll move this over there and close it here for now.

I'd like to add to @kitsonk's excellent explanation that you might be able to workaround this by changing the export order of some of your barrels/modules.

I can't explain it well in generic terms since it really depends on how you organized your barrels and where your webpack entry points are, but a good rule of thumb would be to always export higher level classes at the bottom and its dependencies at the top.

Thanks for your imput @cvsguimaraes. In the end it all came down to the fact that TypeScript assumes that module imports do not have side effects.

See here for more info: https://github.com/webpack/webpack/issues/4520#issuecomment-288228218

Hi,

We have the same error. Currently it is difficult to find the cycle and I was hoping this could be fixed or the error could be improved.

But it's unclear to me if this is now a Webpack or typescript issue? (it's closed on both repos)

But it's unclear to me if this is now a Webpack or typescript issue? (it's closed on both repos)

@304NotModified See this comment from webpack author on the issue.

i am facing the same issue and cant find exact root cause of this error.

As stated in the comment that @cvsguimaraes linked to, this isn't either a TypeScript or WebPack issue. It is an effect of how ES6 modules are parsed.

Circular dependencies will be your downfall and arguably a bad design decision. They are fragile. TypeScript is not disallowing it, which I guess would be the only argument, in that when you have an import order issue that cannot be resolved.

@kitsonk all i am doing is extending classes to base api class. Does this mean i should change the code and not use class extends?

This particular issue has to do with circular references, where A.ts depends on B.ts which depends on A.ts.

all i am doing is extending classes to base api class

Clearly that can' be the case, if you are encountering this issue.

What would be the way to fix it ? change the imports or not use extend and use it as

private api: BaseApi = new BaseApi();

You are giving one line of code and saying _how do I fix it?_ when you have even indicated what the problem is. The code you are quoting doesn't even reference the code at the top of this issue.

You should be asking "how do I" questions on Gitter or StackOverflow, providing an appropriate level of information on what the problem is.

So i am extending providers with base api provider.

HistoryRequestProvider is one of the provider extending to ApiService. there are around 10+ providers which extend to ApiService.

import {Injectable} from '@angular/core';
import {AuthHttp} from 'angular2-jwt';
import {Request} from "./models/request.model";
import {EventService} from "../../services/event.service";
import {ApiService} from "../../services/base.service";
import {Observable} from "rxjs";

@Injectable()
export class HistoryRequestProvider extends ApiService<Request> {
    protected model = Request;
    protected endpoint: string = 'me/requests/history';

    constructor(protected auth:AuthHttp, protected events:EventService) {
        super();
    }
}
export abstract class ApiService<T extends GenericMayHaveId> extends ApiHelper<T> {
    protected baseUrl: string = Config.apiUrl;
    protected dataStore: DataStore<any> = new DataStore();
    protected ram: DataStore<any> = new DataStore();
    protected activeStore: string;

    protected endpoint: string;
    protected auth: AuthHttp;
    protected events: EventService;
}
export interface GenericMayHaveId {
    id?: number|string;
    updated_at?: Date|DateTime;
    created_at?: Date|DateTime;
}
export abstract class ApiHelper<T> {
    protected contentHeader: Headers = new Headers(
        Object.assign(apiVersionHeader, {"Content-Type": "application/json"})
    );
    protected events: EventService;
    protected initiated: boolean;

    getActiveStore(): any {
    }
}

and this is the error i get

image

image

listing all providers.
image

The issue tracker is for tracking issues with TypeScript itself, not issues with user code.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wmaurer picture wmaurer  ·  3Comments

Antony-Jones picture Antony-Jones  ·  3Comments

kyasbal-1994 picture kyasbal-1994  ·  3Comments

remojansen picture remojansen  ·  3Comments

fwanicka picture fwanicka  ·  3Comments