web-dev-qa-db-ja.com

TypeError:オブジェクトプロトタイプはオブジェクトまたはnullのみである可能性があります:未定義

以下でEntityをインポートすると、投稿の件名エラーが発生します(TypeError:ObjectプロトタイプはObjectまたはnull:undefinedの可能性があります)が、インポートを実際のEntity宣言で置き換えると、コードうまくいきます。

Stackblitzのデモはこちら

これは Customer.tsでコードを実行するとエラーが発生する形式でts-node

index.ts

export { Customer } from "./Customer";
export { Entity } from "./Entity";

Customer.ts

import { Entity } from "./index";

export class Customer extends Entity {
  sku: string;
  constructor(po: any) {
    super();
    this.sku = po.sku;
  }
}

Entity.ts

export abstract class Entity {
  id?: string;
}    

Run.ts(テストコード)

import {Customer} from "./";

let c = new Customer({
  name: "Bob"
});
console.log(c);

Entityインポートを次のような宣言に置き換えると、

export abstract class Entity {
  id?: string;
}    

export class Customer extends Entity {
  sku: string;
  constructor(po: any) {
    super();
    this.sku = po.sku;
  }
}

次にRun.tsこれをログに記録します:

Customer { sku: undefined }

つまり、問題なく実行され、エラーは発生しません。考え?

8
Ole

私が疑ったように、元のプログラムには循環インポートがあります。 Run.tsindex.tsをインポートし、Customer.tsindex.tsを再度インポートします。 index.tsは既に読み込み処理中であり、それ自体がCustomer.tsに依存しているため、import { Entity } from "./index";index.tsEntityをバインドするだけです(まだ設定されていません) )をCustomer.tsEntityに変更すると、index.tsの読み込みが完了していなくても実行が続行されます。その場合、Entityは、拡張しようとした時点では未定義です。循環インポートはエラーになるか、JavaScriptエンジンはシナリオを正しく処理する他のアルゴリズムを使用する必要があると主張するかもしれません。現在のデザインが選ばれた理由についてコメントする資格はありません。 (他の人もこれについての情報を自由に追加してください。)

ご覧のとおり、Customer.ts./Entityではなく./indexから直接インポートするように変更すると、サイクルが中断され、すべてが期待どおりに機能します。別の解決策は、index.tsのインポートの順序を逆にすることです。

11
Matt McCutchen