TypeError: Class extends value undefined is not a function or null
Asked Answered
W

23

223

I am getting the following error when trying to create these entities.

TypeError: Class extends value undefined is not a function or null

I am assuming this has something to do with circular dependencies, but how is that supposed to be avoided when using table inheritance and one to many relationships?

It is complaining about the following javascript at BaseComic_1.BaseComic.

let Variant = class Variant extends BaseComic_1.BaseComic {

Here is the complete file.

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
const typeorm_1 = require("typeorm");
const Comic_1 = require("./Comic");
const BaseComic_1 = require("./BaseComic");
let Variant = class Variant extends BaseComic_1.BaseComic {
};
__decorate([
    typeorm_1.ManyToOne(type => Comic_1.Comic, comic => comic.variants),
    __metadata("design:type", Comic_1.Comic)
], Variant.prototype, "comic", void 0);
Variant = __decorate([
    typeorm_1.ClassEntityChild()
], Variant);
exports.Variant = Variant;
//# sourceMappingURL=Variant.js.map

import {Entity, Column, PrimaryGeneratedColumn, OneToMany} from "typeorm";
import {Comic} from "./Comic";

@Entity()
export class Series {

    @PrimaryGeneratedColumn()
    public id: number;

    @Column("text", {
        length: 30
    })
    public copyright: string;

    @Column("text", {
        length: 100
    })
    public attributionText: string;

    @Column("text", {
        length: 150
    })
    public attributionHTML: string;

    @Column("text", {
        length: 50
    })
    public etag: string;

    @Column("text", {
        length: 200
    })
    public title: string;

    @Column("text")
    public description: string;

    @Column("number", {
        length: 4
    })
    public startYear: number;

    @Column("number", {
        length: 4
    })
    public endYear: number;

    @Column("text", {
        length: 20
    })
    public rating: string;

    @Column("text", {
        length: 20
    })
    public type: string;

    @Column("text")
    public thumbnail: string;

    @OneToMany(type => Comic, comic => comic.series)
    public comics: Array<Comic>;
}

import {Entity, TableInheritance, PrimaryGeneratedColumn, Column, ManyToOne, DiscriminatorColumn} from "typeorm";
import {Series} from "./Series";

@Entity()
@TableInheritance("class-table")
@DiscriminatorColumn({ name: "type", type: "string"})
export class BaseComic {

    @PrimaryGeneratedColumn()
    public id: number;

    @Column("text", {
        length: 30
    })
    public copyright: string;

    @Column("text", {
        length: 100
    })
    public attributionText: string;

    @Column("text", {
        length: 150
    })
    public attributionHTML: string;

    @Column("text", {
        length: 50
    })
    public etag: string;

    @Column("text", {
        length: 200
    })
    public title: string;

    @Column("int")
    public issue: number;

    @Column("text")
    public variantDescription: string;

    @Column("boolean")
    public variant: boolean;

    @Column("text")
    public description: string;

    @Column("int")
    public pageCount: number;

    @Column("date")
    public onSaleDate: Date;

    @Column("date")
    public unlimitedDate: Date;

    @Column("text")
    public thumbnail: string;

    @ManyToOne(type => Series, series => series.comics)
    public series: Series;
}

import {OneToMany, ClassEntityChild} from "typeorm";
import {Variant} from "./Variant";
import {BaseComic} from "./BaseComic";

@ClassEntityChild()
export class Comic extends BaseComic {

    @OneToMany(type => Variant, variant => variant.comic)
    public variants: Variant[];
}

import {ManyToOne, ClassEntityChild} from "typeorm";
import {Comic} from "./Comic";
import {BaseComic} from "./BaseComic";

@ClassEntityChild()
export class Variant extends BaseComic {

    @ManyToOne(type => Comic, comic => comic.variants)
    public comic: Comic;
}
Wellchosen answered 3/4, 2017 at 3:13 Comment(0)
U
292

I was having the same issue. It turns out I was circularly importing classes, which is apparently a limitation. (See these GitHub issues: #20361, #4149, #10712)

Note that it seems that the circular reference is also limited between files, not simply types.

See this other answer

Unrobe answered 23/6, 2017 at 18:8 Comment(9)
I had a circular import issue with browserify. It was inconsistent and weird--modifying the file or commenting and removing things and rerunning would sometimes make it go away. Tricky.Pickar
Note that it seems that the circular reference is between files, not simply types. So even when your type references are not circular, you may still have this problem depending on the .ts files your types reside in.Bolingbroke
@JoshuaKing can you link to a resource regarding that "limitation" of cirtualr importing classes in typescript?Victoir
From my experience also the order of imports is important. I had a User entity und 2 other entities which had the same abstract class. The other 2 entities also imported the User and as long as the abstract class was the last import (mainly after user) everything was fine. As soon as i ordered the imports in another way the application broke.Tycoon
@BrunoBieri it's not Typescript's limitation. This is a runtime error - the module resolver is unable to navigate it's way around the circular import. A good resource I've found is in You Don't Know JS.Morn
I just ran into a circular dependency causing this error, however the issue wasn't circular exports, it was circular files. The default exported class also had exported constants, and those constants were causing a circular dependency. When another class tried to extend the first class, this issue reared it's ugly head. Cost me a full day here. Remember: Circular dependencies are file based, not export based.Kornegay
Due to the large number of possible dependencies, it helps to use a checker like Madge. npm i --saveDev madge; node_modules/madge/bin/cli.js --warning --circular --extensions ts ./ Needs explicit import paths (no omitted 'index'), still worthwhile.Tedra
I humbly suggest editing the answer and bolding the also applies to circular files part!Americano
We also had the same issue in TypeScript project, our issue caused by bad practice of COMMON CONST import. we had shared constants not in a common path in the project.Polarization
R
62

As noted in Thomas Jensen's comment above, circular references can occur not just in Types, but also in files. I encountered this same problem when I was exporting both the base and derived types from the same file. Such as:

// index.ts
export { BaseClass } from "./base";
export { DerivedClass } from "./derived";

This is an easy pitfall to fall into. Posting this here in the hopes it'll save someone else the debugging time.

Remus answered 12/3, 2019 at 1:26 Comment(8)
so what is the best work around for this when you have an index file like this. where do you put the base files? Or is an index file kinda of an anti-patternAutoeroticism
I don't think index.ts files are an anti-pattern, I know some people disagree with that. I think they're a great way to provide a useful public interface to a module. From memory I ended up resolving this issue by refactoring to not require exporting the base class at all. Unfortunately I can't give you a better answer than that.Remus
there's something oddly poetic about "pitfall to fall into" in a post about circular references... :)Burgenland
@NathanBeach, that's why it is called a tautology. :)Compander
This was the issue for me, I had to put the two classes in separate filesThermograph
I have a circular reference with imports between my base model and my database adapter, which is bad and I'm about to fix it, but it's still working. What prevented me from starting was some test code in the adapter and once I moved it to a unit test where it belongs this error went away.Lesleylesli
I ran into this same scenario, where I had an instance of derived class in the base class. Thank youEngrail
So there is no way to export both the base class and derived class?Pops
A
55

Circular dependencies can be tricky to identify. Michael Weststrate has an interesting reading about circular dependencies and proposed a pattern to fix them.

Automated circular dependency detection.

On top of using a pattern that allows for scalability, you can make use of a super useful tool that with very little effort will identify circular dependencies for you, Madge.

Madge can be ran over .ts or .js files. I found that is useful to run it in both directories, as they might give different results due to the transpilation process.

For Typescript .ts files:

madge --circular --extensions ts <directory_path>

For Javascript .js files:

madge --circular <directory_path>
Adur answered 5/7, 2020 at 15:13 Comment(3)
Thank you for sharing this. Weirdly I got No circular dependency found! yet the thing still throws the same error. Though it doesn't solve my problem, I would have spent ages looking for a circular dependency if it weren't for this.Ourself
I want to put in good word for dpdm an alternative to Madge. In my code, Madge found 1 trivial circular dependency and wasn't helpful at all; dpdm, on the other hand, found 27 substantive circular paths. Recommended.Cemetery
@JoshHansen does dpdm search recursively if a directory is given? I'm pretty sure madge doesn't, and from the github it seems rather abandoned, both reasons enough to prefer dpdm, but the latter doesn't report how many files it analysed so it's hard to tell whether it ignore any subdirectories.Temporal
B
9

I came here because when executing the code with jest, it threw this error. This is because when writing the moduleNameMapper for the jest.config.js the order of the elements in the object is essential.

There is a helper which imports the module-names from the ts-config.json:

// jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest/utils');
// In the following statement, replace `./tsconfig` with the path to your `tsconfig` file
// which contains the path mapping (ie the `compilerOptions.paths` option):
const { compilerOptions } = require('./tsconfig');

module.exports = {
  // [...]
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths /*, { prefix: '<rootDir>/' } */ )
};

Taken from the official documentation of ts-jest

Bord answered 16/4, 2020 at 11:52 Comment(1)
yes, I saw this error when I wasn't mocking things in jest properly - specifically, when mocking an entire module via __mocks__, all symbols used from there need to be mocked (or unmocked with requireActual, etc)Outcross
L
6

Just ran into this issue and, well, it is strange. I am running the project as

node --require ts-node/register path/to/index.ts

And this failed with above error even after I removed circular references as suggested by accepted answer.

However, if I run tsc it compiles fine and then it runs fine even with --require ts-node/register....

Hope this helps someone.

Lias answered 8/9, 2019 at 2:46 Comment(0)
C
3

For me, I wanted to have a base entity that performs common tasks for all child entiies with method like @BeforeInsert etc. So my structure was this one:

entity/
-- index.ts
-- base.entity.ts
-- foo/
-- --foo.entity.ts

In the index.ts

export { default as MyBaseEntity } from './base.entity'; // <-- This was the problem
export { default as FooEntity } from './foo/foo.entity';

base.entity.ts

import {
  BaseEntity, BeforeInsert,
  CreateDateColumn,
  ObjectIdColumn,
  UpdateDateColumn
} from 'typeorm';
import { v4 as uuidv4 } from 'uuid';

export class MyBaseEntity extends BaseEntity {
  @ObjectIdColumn()
  id!: string;

  @CreateDateColumn({name: 'created_at'})
  createdAt: Date;

  @UpdateDateColumn({name: 'updated_at'})
  updatedAt: Date;

  @BeforeInsert()
  beforeInsert() {
    this.id = uuidv4();
  }
}

and my foo.entity.ts

import {
  BaseEntity, BeforeInsert,
  CreateDateColumn,
  ObjectIdColumn,
  UpdateDateColumn
} from 'typeorm';
import {Injectable} from '@nestjs/common';
import { MyBaseEntity } from './../base.entity';

@Injectable()
@Entity('foo')
export class FooEntity extends MyBaseEntity {}

The circular file dependency came from the index.ts exports. I just had to remove the export of the base.entity

Conception answered 5/2, 2023 at 4:7 Comment(0)
A
2

I had the same error.

The reason was that my index.vue single file component made import of the index.ts file which contained common logic:

// index.vue

import Impl from './index'

and the file structure was:

/my-component
  index.vue
  index.ts

As I understand, index.vue imported itself. So, I just renamed index.ts to common.ts.

Appreciate answered 15/9, 2022 at 17:9 Comment(0)
L
1

The internal module pattern

try this example to solve circular dependency. details you can find Here

// -- app.js --
import { AbstractNode } from './internal'

/* as is */

// -- internal.js --
export * from './AbstractNode'
export * from './Node'
export * from './Leaf'

// -- AbstractNode.js --
import { Node, Leaf } from './internal'

export class AbstractNode {
   /* as is */
}

// -- Node.js --
import { AbstractNode } from './internal'

export class Node extends AbstractNode {
   /* as is */
}

// -- Leaf.js --
import { AbstractNode } from './internal'

export class Leaf extends AbstractNode {
   /* as is */
}
Leeanneleeboard answered 26/4, 2021 at 6:16 Comment(1)
The best idea by a long sea mile to get a consistent, clean, maintainable import. Should get way more upvotes.Nepos
D
1

For me, it was not circular dependency. This is for Angular web app.

I had an abstract class:

export abstract class BaseService {
  ...
}

and I was trying to extend it to implement an Angular service,

@Injectable({
  providedIn: 'root'
})
export class MyExtendedService extends BaseService {

But, I keep getting the error TypeError: Class extends value undefined is not a function or null in my app.module.ts where I was implementing this extension.

After lot of trial and error, I found out that I had to add @Injectable to the base class also. So, I updated my base class to:

@Injectable()
export abstract class BaseService {
  ...
}

and then, everything worked fine.

Dualistic answered 25/4, 2022 at 12:49 Comment(0)
W
1

In Next.js 13, for me, it got solved by upgrading the node version to 16.

Wodge answered 9/5, 2023 at 4:32 Comment(0)
V
0

I had the same problem because my editor auto-imported Entity from the wrong package.

Once I changed import { Entity } from 'typeorm/decorator/entity/Entity'; back to import { Entity } from 'typeorm'; the error message disappeared.

Varden answered 26/5, 2020 at 11:55 Comment(0)
H
0

1. Designing a React Component:

class Card extends React.Compoonent {

See the typo: Compoonent

2. Installing Angular on Windows fails with error:

TypeError: Class extends value undefined is not a function or null

  1. Start > Run > AppWiz.cpl > Uninstall node.js

  2. Delete the node install directory removing remaining folders and files

  3. Delete npm folder from Start > Run > %AppData% (AppData\Roaming)

  4. If it exists delete npm-cache from the c:\users[username} directory

  5. Install node.js the Latest Version and please use the default C:\Program Files\nodejs install path.

  6. Open Cmd:


C:\Users\Jeremy>node -v
v17.1.0

C:\Users\Jeremy>npm -v
8.1.2
Hellbender answered 12/11, 2021 at 6:23 Comment(0)
M
0

In my node typescript project, I was using import/export syntax (over require).

I had this error in a file where I forgot to get rid of the module.exports syntax :

module.exports = { AbstractClass } // this will cause issues if you use import/export syntax

I just had to remove it and simply use the "export" key word

export class AbstractClass { /* stuff */ }
Mcgaw answered 11/1, 2022 at 15:38 Comment(0)
J
0

I had this identical error using ES6 with a base class and inheritence (extends keyword i.e... export class Arrow extends Pointer {}).

None of the suggestions helped me resolve my issue until I read something about replacing the "export" keyword with module.exports... I checked my base class and realized I forgot to include the export keyword before my class signature...

class Pointer {}

became

export class Pointer {}

Making that one change eliminated my error.

Jacobjacoba answered 24/7, 2022 at 21:15 Comment(0)
H
0

While updating my Angular version from 8 to 9, I was originally getting a typescript compilation error and had to upgrade to node 14.20.1. After that upgrade I started seeing the above error. It turns out that the @angular-devkit/build-angular was a recent version (15.0.0 or something like that) and my upgraded Angular project was 8.2. So it was just a matter of downgrading this package. Here's a compatibility chart: https://www.npmpeer.dev/packages/@angular-devkit/build-angular/compatibility

It turns out that the @angular-devkit/build-angular package is extremely important in generating the correct files in node modules and executing the build successfully.

Hun answered 23/12, 2022 at 16:31 Comment(0)
L
0

A bit unrelated, but might be helpful for some. Got a very similar Error in React which read Class extends value undefined is not a constructor or null

The issue was that I wrote class App extends React.Component () { instead of class App extends React.Component {

Laurentia answered 12/2, 2023 at 18:25 Comment(0)
J
0

For me React was importing from a path in project instead of it being from react dependency and so the class couldn't extend from it.

import React from 'react';
Jardena answered 1/3, 2023 at 2:51 Comment(0)
F
0

Firstly, i will check naming extends for class: extends React.Components

Forewent answered 6/3, 2023 at 9:40 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewEvelunn
S
0

For me the problem was re-organized imports. I reverted to the order imports was initially in to resolve the problem.

Slag answered 27/3, 2023 at 18:13 Comment(0)
L
0

In my case, I was using Next JS version 13.4.12 & also App Router (aka app dir).

I was trying to use a UI library which was unable to render on server side.

So converting the component to a Client Component solved this error.

"use client";

// import statements

// code
Lutenist answered 9/8, 2023 at 22:57 Comment(0)
B
0

For me I just removed node_modules & then reinstalled node_modules, everything started working again.

For me this happened after I installed new package like : npm i <package>

rm -rf node_modules

npm install
Bunko answered 28/12, 2023 at 19:35 Comment(0)
K
-1

I received this error because I installed Node.js into the folder C:\applications (not the default one, which is C:\Program Files\nodejs)

It's strange, but after re-installing Node.js into the default location I can successfully run npm install on my freshly cloned project.

Kannan answered 15/2, 2022 at 10:51 Comment(0)
D
-1

Check the Component word spelling

Dogma answered 12/3, 2023 at 12:16 Comment(2)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewGoiter
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Gerrit

© 2022 - 2024 — McMap. All rights reserved.