TypeError: Klasse erweitert Wert undefiniert ist keine Funktion oder null

74

Beim Versuch, diese Entitäten zu erstellen, wird die folgende Fehlermeldung angezeigt.

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

Ich gehe davon aus, dass dies etwas mit zirkulären Abhängigkeiten zu tun hat, aber wie soll dies vermieden werden, wenn Tabellenvererbung und eine bis viele Beziehungen verwendet werden?

Es beschwert sich über das folgende Javascript bei BaseComic_1.BaseComic.

let Variant = class Variant extends BaseComic_1.BaseComic {

Hier ist die komplette Datei.

"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;
}
prolink007
quelle

Antworten:

116

Ich hatte das gleiche Problem. Es stellte sich heraus, dass ich zirkulär Klassen importierte, was anscheinend eine Einschränkung ist. (Siehe diese GitHub-Probleme: # 20361 , # 4149 , # 10712 )

Beachten Sie, dass der Zirkelverweis anscheinend auch auf Dateien beschränkt ist, nicht nur auf Typen.

Siehe diese andere Antwort

Joshua King
quelle
1
Ich hatte ein Problem mit dem zirkulären Import von browserify. Es war inkonsistent und seltsam - das Ändern der Datei oder das Kommentieren und Entfernen von Dingen und das erneute Ausführen ließen sie manchmal verschwinden. Tricky.
user1978019
6
Beachten Sie, dass der Zirkelverweis anscheinend zwischen Dateien und nicht nur zwischen Typen liegt . Selbst wenn Ihre
Typreferenzen
2
@JoshuaKing Können Sie einen Link zu einer Ressource bezüglich dieser "Einschränkung" des Importierens von Cirtualr-Klassen in Typoskript erstellen?
Bruno Bieri
1
Aus meiner Erfahrung ist auch die Reihenfolge der Importe wichtig. Ich hatte eine Benutzerentität und 2 andere Entitäten, die dieselbe abstrakte Klasse hatten. Die anderen beiden Entitäten importierten ebenfalls den Benutzer und solange die abstrakte Klasse der letzte Import war (hauptsächlich nach dem Benutzer), war alles in Ordnung. Sobald ich die Importe auf andere Weise bestellt hatte, brach die Anwendung.
Tobias Stangl
1
@BrunoBieri ist nicht die Einschränkung von Typescript. Dies ist ein Laufzeitfehler. Der Modul-Resolver kann sich nicht im zirkulären Import zurechtfinden. Eine gute Ressource, die ich gefunden habe, ist in You Don't Know JS .
Gombosg
16

Wie im obigen Kommentar von Thomas Jensen erwähnt, können Zirkelverweise nicht nur in Typen, sondern auch in Dateien vorkommen. Ich habe dasselbe Problem festgestellt, als ich sowohl den Basis- als auch den abgeleiteten Typ aus derselben Datei exportiert habe. Sowie:

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

Dies ist eine leichte Falle, in die man fallen kann. Wenn Sie dies hier veröffentlichen, in der Hoffnung, dass dies jemand anderem die Debugging-Zeit erspart.

ajxs
quelle
Was ist die beste Lösung dafür, wenn Sie eine Indexdatei wie diese haben? Wo legen Sie die Basisdateien ab? Oder ist eine Indexdatei eine Art Anti-Muster
Jonathan
Ich denke nicht, dass index.tsDateien ein Anti-Muster sind, ich weiß, dass einige Leute damit nicht einverstanden sind. Ich denke, sie sind eine großartige Möglichkeit, eine nützliche öffentliche Schnittstelle zu einem Modul bereitzustellen. Aus dem Speicher heraus habe ich dieses Problem durch Refactoring behoben, sodass die Basisklasse überhaupt nicht exportiert werden muss. Leider kann ich Ihnen keine bessere Antwort geben.
Ajxs
2

Ich bin gerade auf dieses Problem gestoßen und es ist seltsam. Ich leite das Projekt als

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

Und dies schlug mit dem obigen Fehler fehl, selbst nachdem ich Zirkelverweise entfernt hatte, wie durch die akzeptierte Antwort vorgeschlagen.

Wenn ich es jedoch ausführe, wird tsces gut kompiliert und dann läuft es auch mit --require ts-node/register....

Hoffe das hilft jemandem.

PeS
quelle
2

Zirkuläre Abhängigkeiten können schwierig zu identifizieren sein. Michael Weststrate hat eine interessante Lektüre über zirkuläre Abhängigkeiten und schlug ein Muster vor, um diese zu beheben.

Automatische Erkennung kreisförmiger Abhängigkeiten.

Neben der Verwendung eines Musters, das Skalierbarkeit ermöglicht, können Sie ein äußerst nützliches Tool verwenden, mit dem Sie mit sehr geringem Aufwand zirkuläre Abhängigkeiten identifizieren können, Madge .

Madge kann überfahren werden .tsoder .jsDateien. Ich fand es nützlich, es in beiden Verzeichnissen auszuführen, da sie aufgrund des Transpilationsprozesses unterschiedliche Ergebnisse liefern können.

Für .js-Dateien : madge --circular --extensions ts <Verzeichnispfad>

Für .ts-Dateien : madge --circular <Verzeichnispfad>

JesusIniesta
quelle
0

Ich bin hierher gekommen, weil beim Ausführen des Codes mit Scherz dieser Fehler aufgetreten ist. Dies liegt daran, dass beim Schreiben der moduleNameMapperfür die jest.config.jsReihenfolge der Elemente im Objekt wesentlich ist.

Es gibt einen Helfer, der die Modulnamen importiert aus 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>/' } */ )
};

Entnommen aus der offiziellen Dokumentation von ts-jest

InsOp
quelle
0

Ich hatte das gleiche Problem, weil mein Editor automatisch Entityaus dem falschen Paket importiert wurde .

Sobald ich import { Entity } from 'typeorm/decorator/entity/Entity';wieder auf import { Entity } from 'typeorm';die Fehlermeldung umgestellt habe , verschwand sie.

Marvin Scharle
quelle