[解決済み】TypeScriptの外部モジュールで名前空間を使用するにはどうすればいいですか?
質問
私はいくつかのコードを持っています。
baseTypes.ts
export namespace Living.Things {
export class Animal {
move() { /* ... */ }
}
export class Plant {
photosynthesize() { /* ... */ }
}
}
dog.ts
import b = require('./baseTypes');
export namespace Living.Things {
// Error, can't find name 'Animal', ??
export class Dog extends Animal {
woof() { }
}
}
tree.ts
// Error, can't use the same name twice, ??
import b = require('./baseTypes');
import b = require('./dogs');
namespace Living.Things {
// Why do I have to write b.Living.Things.Plant instead of b.Plant??
class Tree extends b.Living.Things.Plant {
}
}
これは非常に分かりにくいですね。私は、たくさんの外部モジュールに同じ名前空間に型を提供させたいと思っています。
Living.Things
. これはまったくうまくいかないようです。
Animal
で
dogs.ts
. 完全な名前空間名を書かなければなりません。
b.Living.Things.Plant
で
tree.ts
. ファイルをまたいで同じ名前空間にある複数のオブジェクトを結合するのはうまくいきません。どうすればいいのでしょうか?
解決方法は?
キャンディーカップの例え
バージョン1:お菓子の数だけカップがある
例えば、こんなコードを書いたとしよう。
Mod1.ts
export namespace A {
export class Twix { ... }
}
Mod2.ts
export namespace A {
export class PeanutButterCup { ... }
}
Mod3.ts
export namespace A {
export class KitKat { ... }
}
各モジュール(紙)には
専用カップ
名前
A
. これは無駄です。
オーガナイズ
お菓子と自分の間に新たなステップ(カップからお菓子を取り出す)が加わるだけです。
バージョン2:グローバルスコープに1つのカップ
もし、モジュールを使っていなかったら、次のようなコードを書くかもしれません。
export
の宣言があります)。
グローバル1.ts
namespace A {
export class Twix { ... }
}
グローバル2.ts
namespace A {
export class PeanutButterCup { ... }
}
グローバル3.ts
namespace A {
export class KitKat { ... }
}
これは
のコードは、マージされた名前空間を作成します。
A
をグローバルスコープで表示します。
この設定は便利ですが、モジュールの場合には適用されません(モジュールはグローバルスコープを汚さないからです)。
バージョン3:カップレス化
元の例に戻ると、カップは
A
,
A
および
A
は、あなたのためにならない。その代わり、次のようにコードを書くことができます。
Mod1.ts
export class Twix { ... }
Mod2.ts
export class PeanutButterCup { ... }
Mod3.ts
export class KitKat { ... }
を使うと、このような絵になります。
ずっといい!
さて、もしあなたがまだ、自分のモジュールでどれだけ名前空間を使いたいか考えているのなら、続きを読んでください...。
これらはあなたが探している概念ではありません
そもそもなぜ名前空間が存在するのかという原点に立ち返り、その理由が外部モジュールに意味を持つかどうかを検証する必要があります。
組織
: 名前空間は、論理的に関連するオブジェクトや型をグループ化するのに便利です。例えば、C#では、すべてのコレクション型は
System.Collections
. このように、型を階層的な名前空間に整理することで、その型を利用するユーザーに対して、より良い「発見」の体験を提供することができるのです。
名前の衝突
: 名前空間は、名前の衝突を避けるために重要です。たとえば
My.Application.Customer.AddForm
と
My.Application.Order.AddForm
-- 同じ名前だが名前空間が異なる2つの型。すべての識別子が同じルートスコープに存在し、すべてのアセンブリがすべての型を読み込む言語では、すべてが名前空間内にあることが重要です。
そのような理由は、外部モジュールでも意味を持つのでしょうか?
組織
: 外部モジュールは、必然的にファイルシステムに既に存在している。パスとファイル名で解決しなければならないので、論理的な組織化スキームがある。私たちは
/collections/generic/
フォルダに
list
モジュールが含まれています。
名前の衝突 : 外部モジュールでは全く適用されません。 内 モジュールで、同じ名前のオブジェクトを2つ持つもっともな理由はありません。消費側からは 消費者 は、そのモジュールを参照するために使用する名前を選ぶことができるので、偶発的な名前の衝突はあり得ません。
これらの理由がモジュールの仕組みによって適切に対処されているとは思えないとしても、外部モジュールで名前空間を使おうという "解決策"は機能さえしません。
箱の中の箱の中の箱
ある物語
友人のボブから電話があり、「僕の家に素晴らしい整理術があるんだ」と言う。すてきですね、ボブが何を考え出したのか見に行きましょう。
まずキッチンから始めて、パントリーを開ける。60種類の箱があり、それぞれに「パントリー」と書かれています。あなたはランダムに箱を選び、それを開きます。中には「Grains」と書かれた箱が1つ入っています。Grains"の箱を開けると、Pasta"と書かれた箱が1つあります。Pastaの箱を開けると、Penneと書かれた箱が1つあります。この箱を開けると、期待通り、ペンネパスタが1袋入っていました。
少し混乱して、隣の箱を手に取ると、これまた「Pantry"」と書かれています。中には1つの箱があり、やはり「Grains"」と書かれています。Grains"の箱を開けると、またまた「Pasta"」と書かれた箱が1つ入っています。Pastaの箱を開けると、「Rigatoni」と書かれた箱が1つあります。この箱を開けると...リガトーニパスタが1袋入っていました。
とボブは言っています。
でも、ボブ......」とあなたは答えます。「あなたの構成法は役に立たない。何かを見つけるにはたくさんの箱を開けなければならないし、実際に何かを見つけるのに便利というわけでもない。 一つ ボックスではなく スリー . 実は、パントリーはすでに棚ごとに分類されているので、箱はまったく必要ないのです。パスタを棚にセットして、必要な時に手に取ればいいじゃないですか"。
パントリー」という名前空間にふさわしくないものを誰も入れないようにする必要があるんです。そして、私はすべてのパスタを安全に
Pantry.Grains.Pasta
という名前空間があるので、簡単に見つけることができます。ボブはとても混乱した男です。
モジュールは自分たちの箱
皆さんも、同じようなことが現実に起こったことがあるのではないでしょうか。Amazonでいくつかの商品を注文すると、それぞれの商品が専用の箱に入って現れ、その中にさらに小さな箱があり、商品が独自の包装で包まれている。内箱が同じようなものであったとしても、配送はquot;combined"にはなりません。
箱の例えで行くと、重要な観察は以下の通りです。 外部モジュールはそれ自体が箱である . 多くの機能を持つ非常に複雑なアイテムかもしれませんが、与えられた外部モジュールはそれ自体が箱なのです。
外部モジュールに関するガイダンス
さて、「名前空間」を使う必要がないことがわかったところで、どのようにモジュールを整理すればいいのでしょうか?いくつかの指針や例を以下に示します。
できるだけトップレベルに近い形でエクスポートする
-
単一のクラスや関数をエクスポートするだけなら
export default
:
MyClass.ts
export default class SomeType {
constructor() { ... }
}
MyFunc.ts
function getThing() { return 'thing'; }
export default getThing;
消費量
import t from './MyClass';
import f from './MyFunc';
var x = new t();
console.log(f());
これは消費者にとって最適です。彼らはあなたのタイプに好きな名前をつけることができます (
t
この場合、オブジェクトを見つけるために余計なドット打ちをする必要はありません。
- 複数のオブジェクトをエクスポートする場合、それらをすべてトップレベルに配置します。
MyThings.ts
export class SomeType { ... }
export function someFunc() { ... }
消費量
import * as m from './MyThings';
var x = new m.SomeType();
var y = m.someFunc();
-
大量のものをエクスポートする場合は、そのときだけ
module
/namespace
というキーワードがあります。
MyLargeModule.ts
export namespace Animals {
export class Dog { ... }
export class Cat { ... }
}
export namespace Plants {
export class Tree { ... }
}
消費量
import { Animals, Plants} from './MyLargeModule';
var x = new Animals.Dog();
レッドフラッグ
以下はすべて、モジュールの構造化に関するレッドフラグです。もし、これらのうちのどれかがあなたのファイルに当てはまるなら、外部モジュールの名前空間を使おうとしていないかどうか再確認してください。
-
トップレベルの宣言が
export module Foo { ... }
(削除Foo
を追加し、すべてを一段階上に移動させます。) -
を1つ持つファイルは
export class
またはexport function
でない場合はexport default
-
複数のファイルで、同じ
export module Foo {
をトップレベルにしています(これらがひとつにまとまると思ってはいけません)。Foo
!)
関連
-
[解決済み】Heroku:ノードアプリで「このアプリにはデフォルトの言語が検出されませんでした」エラーがスローされる
-
[解決済み】XMLHttpRequestモジュールが定義されていない/見つからない
-
[解決済み] 正規表現で変数を使うには?
-
[解決済み] JavaScriptで要素のクラスを変更するにはどうすればよいですか?
-
[解決済み] jQueryでページを更新するにはどうすればよいですか?
-
[解決済み] JavaScriptでカンマを桁区切りにして数値を表示する方法
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] TypeScriptで文字列を数値に変換する方法とは?
-
[解決済み] ローカルにインストールされたPythonモジュールの一覧を取得するにはどうしたらいいですか?
-
[解決済み] TypeScript で `window` に新しいプロパティを明示的に設定するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】React Js: Uncaught (in promise) SyntaxError: 位置 0 の JSON で予期しないトークン < が発生しました。
-
[解決済み】TypeError: 'undefined'はオブジェクトではありません。
-
[解決済み】ある要素を別の要素に移動させるには?
-
[解決済み】JavaScriptのボタンonclickが機能しない
-
[解決済み】エラー:リクエストのエンティティが大きすぎる
-
[解決済み】XMLパースエラー:ルート要素が見つからない コンソールの場所 FF
-
[解決済み】ETIMEDOUTエラーの対処方法は?
-
[解決済み】Uncaught TypeError: 未定義のプロパティ 'msie' を読み取れない - jQuery tools
-
[解決済み】react router v^4.0.0 Uncaught TypeError: 未定義のプロパティ'location'を読み取れない
-
[解決済み] Typescript es6 import module "File is not a module error".