Typescript: TS4023:エクスポートされた変数「X」は外部モジュール「a / file / path」から名前「Y」を持っているか使用していますが、名前を付けることができません

作成日 2015年11月18日  ·  24コメント  ·  ソース: microsoft/TypeScript

次のように、外部TypeScriptモジュールのセットを作成しようとしています。

// ClassA.ts
export default class ClassA {
  public method() { return true; } 
}

// ModuleB.ts
import ClassA from './ClassA';
var moduleB = {
  ClassA: ClassA
};
export default moduleB;

// ModuleA.ts
import moduleB from './ModuleB';
var moduleA = {
  moduleB: moduleB
}
export default moduleA;

これはコンパイルされ、ライブラリとして提供されるという考え方です。 計画では、ライブラリのコンシューマーは次のようにClassAのインスタンスをインスタンス化します。

import moduleA from './ModuleA';
var anInstance = moduleA.moduleB.ClassA();

これは、予想されるJSにコンパイルされているように見えますが、エラーコンパイラエラーが発生し、詳細情報を見つけるのに苦労しています。

Using tsc v1.6.2
.../src/ModuleA.ts(3,5): error TS4023: Exported variable 'moduleA' has or is using name 'ClassA' from external module ".../src/ClassA" but cannot be named.

ここの誰かがこの問題に光を当てることができますか? 私がやろうとしていることは理にかなっていますか?

Question

最も参考になるコメント

FWIWは通常、Stack Overflowでより迅速な回答が得られますが、ここでは適切に表現された質問を行います。

ここでの問題は、 --declarationフラグを使用しているが、コンパイラーがそのジョブを実行する方法を提供していないことです。

ModuleA.d.tsを発行しようとすると、コンパイラはモジュールの形状を表すオブジェクト型リテラル( { moduleB: { classA: *mumble?* } } )を記述する必要があります。 ただし、スコープ内にclassAを直接参照する名前がないため、「名前を付けることができません」というタイプであり、エラーが発生します。

ClassA importClassAModuleA.tsに追加すると、エラーは解消されます。

全てのコメント24件

ああ-これがこの質問をするのに適した場所ではない場合。 お知らせください。別のメディアに投稿させていただきます。

FWIWは通常、Stack Overflowでより迅速な回答が得られますが、ここでは適切に表現された質問を行います。

ここでの問題は、 --declarationフラグを使用しているが、コンパイラーがそのジョブを実行する方法を提供していないことです。

ModuleA.d.tsを発行しようとすると、コンパイラはモジュールの形状を表すオブジェクト型リテラル( { moduleB: { classA: *mumble?* } } )を記述する必要があります。 ただし、スコープ内にclassAを直接参照する名前がないため、「名前を付けることができません」というタイプであり、エラーが発生します。

ClassA importClassAModuleA.tsに追加すると、エラーは解消されます。

こんにちはライアン-アドバイスREスタックオーバーフローとアドバイスに感謝します-インポートをModuleA追加すると、期待どおりにコンパイルされました。

ここでのちょっとしたコンテキスト-ここでの私の目標は、実際に外部モジュールの宣言を生成することです。 (私が信じている何かがまだ完全に機能していないのですか?#5039?)このインポートは完全に必要かもしれませんが、moduleBがすでにエクスポートしているシンボルをインポートする必要があるのはModuleAにとって少し奇妙に感じます。 その結果、 ModuleBのオブジェクトエクスポートに追加するたびに、インポートをModuleA直接追加する必要があります。

import {moduleB} from './moduleB';
import {ClassA} from './ClassA';

またはModuleB経由(両方の場所でClassAパスの指定を減らすため):

import {moduleB, ClassA} from './moduleB';

TSコンパイラについてはほとんど知らないので、私が言っていることは完全に非現実的かもしれませんが、最初はコンパイラがModuleBがN個のシンボルを含むオブジェクトをエクスポートしていると推測できるように思われるのでModuleAはこれらの記号が必要ですか? ModuleBのインポート情報はすでにあります- ModuleAはそれを使用できますか? インポートためか、それは不可能であろうClassAに完全に内部にあるModuleBので、コンパイラがためにタイプを推測できるという方法はありません、 ClassAの定義を作成するときにModuleA

お時間を割いていただき、誠にありがとうございます。 私は今私の問題を分類したので、上記は主に好奇心です-答えるのを急ぐ必要はありません。

あなたが何を言っているのか正確にはわかりません。 この提案では、 ModuleA.d.tsどのように見えるべきですか?

コンパイラーは、宣言を発行するときに、ユーザーコードに存在しなかった依存関係(つまり、インポートステートメント)を追加しません。 発生するエラーは、コンパイラがエクスポートされた宣言の型注釈を書き込もうとしているが、書き込めなかったことを意味します。 これには、名前にアクセスできない、つまり現在のモジュールにインポートされていない、または元の宣言をシャドウイングしている宣言があるという2つの理由のいずれかが考えられます。

どちらの場合も、回避策は明示的な型注釈を追加することです。型注釈を追加すると、出力に逐語的に出力されます。 もう1つのオプションは、名前にアクセスできることを確認することです。つまり、モジュールへのインポートがあり、モジュールをインポートしているユーザーにとってそれが何を意味するかを理解しています。

@mhegazyは言った:

コンパイラーは、宣言を発行するときに、ユーザーコードに存在しなかった依存関係(つまり、インポートステートメント)を追加しません。

問題は、コードにimportステートメントが常に必要なわけではなく(明らかに、 --declarationsなくても機能するため)、それらを含めるとノイズが多く、 tslintが「未使用のインポート」。 コンパイラが発行されたJavaScriptに依存関係を追加したくない理由はわかりますが、発行された宣言に依存関係を追加することの問題は何ですか?

この提案を追跡するには、問題をログに記録してください。 インポートは依存関係の宣言であり、コンパイラーは、指示がない限り、インポートを作成しないでください。

これは、より深刻な結果をもたらす可能性があります。

moduleA -> moduleB -> moduleC -> moduleD検討してください。

moduleBは、この問題を回避するためにimport { ABC } from 'moduleA'を実行する必要があるものです。

moduleCmoduleBを使用してその署名をエクスポートすると、 moduleBABCからmoduleA ABCを必要とするため、コンパイルに失敗しますが、今回はmoduleBはそれをエクスポートしませんでした。

これは次のいずれかを意味します。

  1. moduleCのハード依存持っている必要がありますmoduleAして、インポートABC
  2. moduleBは、インポートするだけでなく、 ABCを再エクスポートしてから、 moduleCインポートする必要があります。

moduleDが同様のことを行う場合、基本的には依存関係のチェーン全体を知る必要があります。

typingsを使用していて、ブロックする問題があるため、これをテストしてそれが事実であることを証明できませんでした: https

編集:私はそれを再現することができます、そして確かに私のmoduleDはインポートをするためにmoduleAを参照する必要があります。
私の例では:

  • moduleA => redux
  • moduleB => redux-thunk
  • moduleC => redux-thunk上にカスタムコード
  • moduleD =>いくつかのライブラリ
  • ABC => redux Dispatchインターフェース

@unionalで説明されているのと同じ問題があり

この問題を再度開いてください。

発行https://github.com/Microsoft/TypeScript/issues/9944トラックは、宣言の発行フェーズでインポートを追加し

感謝!

インポートを追加する際の問題は、 noUnusedLocalsすると、コンパイラが使用されていない型について文句を言うことです。 明示的な型アノテーションを追加することはできますが、推論が得られません。 例:

class Whatever {
  fetch(uri: string): Promise<void> { }
  ensureFetched = MemoizedFunction<(uri: string) => Promise<void>> = memoize((uri: string) => this.fetch(uri))
}

ensureFetched型注釈を省略したい

私はこれの回避策を見つけました:
tsconfigの場合: include: [ ..., "node_modules/@your_scope/your_library" ]
頑張って楽しんでください:smiley:

@ salim7これにより、コンパイル時間が遅くなり(すでにコンパイルされているはずのライブラリを再コンパイルしているため)、ターゲットライブラリで厳密性設定の最小公分母を使用する必要があります。

@mhegazy問題は次のシナリオで再現されました:

import * as Foo from "./Foo";

export class Bar {
    baz = new Foo.Baz(); // Compiler forgot "Foo." prefix in the type, and throws this error, because "Baz" without perfix is not imported.
    getBaz() { // All the same
       return new Foo.Baz();
    }
}

解決策は、明示的な型を指定することです。

import * as Foo from "./Foo";

export class Bar {
    baz: Foo.Baz = new Foo.Baz(); // ok
    getBaz(): Foo.Baz { // ok
       return new Foo.Baz();
    }
}

上記のサンプルを使用してこれを再現することはできません。 新しいバグを報告し、問題を再現できるように、より多くのコンテキストを提供してください。

@PFightありがとうございます! それは私にとってそれでした!

私は使用時にこの問題に直面しました:

export { IMyInterface } from './file'
````

The solution was to do this:
```ts
import { IMyInterface } from './file'
export { IMyInterface }

しかし、これは本当に必要なはずではありません。

noUnusedLocals扱い方を誰かが理解しましたか?

@yordis // @ts-ignore

@pelotomええ、これは完全に私のせいです、

私はあることを考えていて、別のことを書きました。

TypescriptはnoUnusedLocalsと宣言の間の問題を修正しましたか?

私の現在の回避策は、私にとって完全な苦痛のように感じますが、

import {SomeInterface} from "./SomeFile";

const _dummySomeInterface : undefined|SomeInterface = undefined;
_dummySomeInterface;

//Code that implicitly uses SomeInterface

noUnusedLocals回避し、可能な場合はジェネリックインターフェイスの型推論も可能にします。

このページは役に立ちましたか?
0 / 5 - 0 評価