TypeScriptのモジュール解決はExportとImportを使うことが多いと思いますが、意外とこのあたりは迷いやすいので、整理してみたいと思います。
##Export
宣言をExportするコード例:
//インターフェース
export interface IHello{
greeting (name :string) :string
}
//変数
export const name = "hoge";
//クラス
export class Hello implements IHello{
greeting (name :string){
return "Hello"+name;
}
}
以下の書き方もできます。リネームすることが可能です。
class Hello implements IHello{
greeting (name :string){
return "Hello"+name;
}
}
export {Hello};
export {Hello as myHello}
複数のモジュールを一斉にexportしたときの書き方。
export * from "./SayHello";
##Import
単一のモジュールをimportする場合
import { Hello } from "./SayHello";
let myHello = new Hello();
importするときにリネームしたい場合
import { Hello as MyHello } from "./SayHello";
let myHello = new MyHello();
一度すべてのモジュールをimportしたい場合
import * as hello from "./SayHello";
let myhello = new hello.Hello();
##Default Export
export default class Hello implements IHello {
greeting (name :string){
return "Hello"+name;
}
}
import時に波括弧でくぐる必要はない
import hello from "./SayHello";
functionをdefault exportすることもできます。
export default function (name: string) {
return "Hello"+name;
}
import greeting from "./SayHello";
alert(greeting("hoge"));
##「module.exports」と「require("xxx")」文
一方const moduleXXX = require("moduleXXX")の書き方もたまに見かけますよね、その違いを理解しないままで書いていくと混乱の元になりかねません。
ExportとImportのペアは厳密にいうとEcmaScript2015(ES6)の企画によって定義されています、これに対して、require("moduleXXX")はNode.jsモジュールローディングシステムである。
上の例で説明すると
const moduleXXX = require("moduleXXX")
と参照する場合、参照される側以下のようにエクスポートを定義する。
class Hello implements IHello{
greeting (name :string){
return "Hello"+name;
}
}
module.exports = Hello;
これはNode.jsのモジュールシステムにはmoduleという特別なオブジェクトが存在し、そこのexportsプロパティに代入しているわけです。ちなみにさらに紛らわしいことにmodule.exportsはexportsオブジェクトからでも参照できる、クラスのコンストラクターを公開する場合module.exportsを使い、単純な関数(オブジェクト指向世界でのstaticメソッドのようなもの)はexportsを使ったほうがいいとされているが、exportsを使う場面と遭遇したことはまだありません。ImportとExportに一本でも特に困ることはないので、requireに関していまごろこれぐらい抑えておいて問題ないかと思います。