【问题标题】:TypeError: Class extends value undefined is not a function or nullTypeError: Class extends value undefined is not a function or null
【发布时间】:2017-08-27 19:27:18
【问题描述】:

尝试创建这些实体时出现以下错误。

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

我假设这与循环依赖有关,但是在使用表继承和一对多关系时应该如何避免这种情况?

它在BaseComic_1.BaseComic 抱怨以下javascript。

let Variant = class Variant extends BaseComic_1.BaseComic {

这是完整的文件。

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

【问题讨论】:

    标签: javascript typescript typeorm


    【解决方案1】:

    我遇到了同样的问题。原来我是循环导入类,这显然是一个限制。 (请参阅这些 GitHub 问题:#20361#4149#10712

    请注意,循环引用似乎也仅限于文件之间,而不仅仅是类型。

    this其他答案

    【讨论】:

    • 我在使用 browserify 时遇到了循环导入问题。这是不一致和奇怪的——修改文件或评论和删除内容并重新运行有时会使它消失。棘手。
    • 请注意,循环引用似乎是在文件之间,而不仅仅是类型。因此,即使您的类型引用不是循环的,您可能仍然会遇到此问题,具体取决于您的类型所在的 .ts 文件。
    • @JoshuaKing 您能否链接到有关在 typescript 中导入类的“限制”的资源?
    • 根据我的经验,导入的顺序也很重要。我有一个用户实体和两个具有相同抽象类的其他实体。其他 2 个实体也导入了用户,只要抽象类是最后一次导入(主要是在用户之后),一切都很好。一旦我以另一种方式订购了进口商品,应用程序就崩溃了。
    • @BrunoBieri 这不是 Typescript 的限制。这是一个运行时错误 - 模块解析器无法围绕循环导入导航。我在You Don't Know JS找到了一个很好的资源。
    【解决方案2】:

    正如上面 Thomas Jensen 的评论中所指出的,循环引用不仅可以出现在类型中,还可以出现在文件中。 当我从同一个文件中导出基本类型和派生类型时,我遇到了同样的问题。如:

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

    这是一个容易掉入的陷阱。在这里发布,希望它可以节省其他人的调试时间。

    【讨论】:

    • 那么当您有这样的索引文件时,最好的解决方法是什么。你把基础文件放在哪里?还是索引文件有点像反模式
    • 我不认为index.ts 文件是反模式,我知道有些人不同意这一点。我认为它们是为模块提供有用的公共接口的好方法。从记忆中,我最终通过重构根本不需要导出基类来解决这个问题。很遗憾,我不能给你比这更好的答案了。
    • 在一篇关于循环引用的文章中,关于“陷入的陷阱”有一些奇怪的诗意... :)
    【解决方案3】:

    循环依赖可能很难识别。 Michael Weststrate 有一个关于循环依赖的interesting reading,并提出了一种修复它们的模式。

    自动循环依赖检测。

    除了使用允许可扩展性的模式之外,您还可以使用一个超级有用的工具,只需很少的努力即可为您识别循环依赖关系,Madge

    Madge 可以在 .ts.js 文件上运行。我发现在两个目录中运行它很有用,因为它们可能会由于转译过程而给出不同的结果。

    对于 Typescript .ts 文件

    madge --circular --extensions ts <directory_path>
    

    对于 Javascript .js 文件

    madge --circular <directory_path>
    

    【讨论】:

    • 谢谢,太棒了!
    • 感谢您分享此内容。奇怪的是我没有找到循环依赖!然而事情仍然抛出同样的错误。虽然它不能解决我的问题,但如果不是因为这个,我会花费很长时间寻找循环依赖。
    • 我想对 dpdm 说好话,作为 Madge 的替代品。在我的代码中,Madge 发现了 1 个微不足道的循环依赖,而且根本没有帮助;另一方面,dpdm 发现了 27 条实质性循环路径。推荐。
    【解决方案4】:

    刚刚遇到这个问题,嗯,很奇怪。我正在运行该项目

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

    即使我按照接受的答案的建议删除了循环引用,这也失败并出现上述错误。

    但是,如果我运行 tsc,它可以正常编译,然后即使使用 --require ts-node/register... 也可以正常运行。

    希望这对某人有所帮助。

    【讨论】:

      【解决方案5】:

      我来到这里是因为在用 jest 执行代码时,它抛出了这个错误。 这是因为在为jest.config.js 编写moduleNameMapper 时,对象中元素的顺序至关重要。

      有一个助手可以从 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>/' } */ )
      };
      

      取自official documentation of ts-jest

      【讨论】:

      • 是的,当我没有正确地嘲笑事物时,我看到了这个错误 - 特别是,当通过 __mocks__ 模拟整个模块时,从那里使用的所有符号都需要被模拟(或取消模拟) requireActual等)
      【解决方案6】:

      我遇到了同样的问题,因为我的编辑器从错误的包中自动导入了 Entity

      一旦我将import { Entity } from 'typeorm/decorator/entity/Entity'; 改回import { Entity } from 'typeorm';,错误消息就消失了。

      【讨论】:

        【解决方案7】:

        在 Windows 上安装 Angular 失败并出现错误:

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

        1. 开始 > 运行 > AppWiz.cpl > 卸载 node.js

        2. 删除节点安装目录删除剩余文件夹和文件

        3. 从开始 > 运行 > %AppData% (AppData\Roaming) 删除 npm 文件夹

        4. 如果存在,则从 c:\users[username} 目录中删除 npm-cache

        5. 安装node.js最新版本,请使用默认C:\Program Files\nodejs安装路径。

        6. 打开命令:


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

        【讨论】:

          【解决方案8】:

          在我的节点打字稿项目中,我使用了导入/导出语法(超过要求)。

          我在忘记删除 module.exports 语法的文件中出现此错误:

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

          我只需要删除它并简单地使用“导出”关键字

          export class AbstractClass { /* stuff */ }
          

          【讨论】:

            【解决方案9】:

            内部模块模式

            试试这个例子来解决循环依赖。 详情你可以找到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 */
            }
            

            【讨论】:

              猜你喜欢
              • 2018-07-14
              • 2020-08-27
              • 2022-01-09
              • 1970-01-01
              • 1970-01-01
              • 2021-11-02
              • 2021-10-20
              • 2022-12-02
              • 2022-12-20
              相关资源
              最近更新 更多