モジュールとスクリプト【個人学習まとめ】
モジュール
プログラムをモジュールという単位で分割することができます。
ソースコードの量が多くなってくると、1 つのファイルだけて管理することは難しくなります。
例えば、
- 名前が被ってしまうこと
- 1 つの変更が他のどの部分に影響があるか見つけることが困難であること
などの問題があります。
この問題を解決するために、モジュールと呼ばれる仕組みがあります。
利用方法
利用するには 2 種類のキーワードが必要になります。import
とexport
です。
まずはexport
の例です。
const PI = 3.14;
function square(x: number) {
return x ** 2;
}
class Rectangle {
width: number;
height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
//名前付きエクスポート
export { PI, square, Rectangle };
class.ts ファイルを作成し、変数PI
、関数function
、クラスRectangle
を用意しました。
さらに、export
キーワードを使って、外部から参照できるようにしています。
この export 方法のほかにも次のように、各変数、関数名の前にexport
を記述する方法があります。
- const PI = 3.14;
+ export const PI = 3.14;
- function square(x: number) {
+ export function square(x: number) {
return x ** 2;
}
エクスポートした物を外部ファイルで参照するには、import
キーワードを使用します。
import { PI, square, Rectangle } from "./class.js";
console.log(PI);
const result = square(3);
console.log(result);
const rect = new Rectangle(5, 10);
console.log(rect.getArea());
上記の例では、calc.ts からインポートしています。
インポート時に拡張子.js
を指定しています。これは、エクスポート元ファイルの拡張子は.ts
ファイルですが、実際にコード上で使用されるのはコンパイルされた JavaScript ファイルであるため、.js
拡張子を使います。
型のエクスポートとインポート
変数、関数と同じようにexprt
キーワードを利用してエクスポートすることが可能です。
export interface Point {
x: number;
y: number;
}
export type LengthUnit = "m" | "cm" | "mm";
このほかにも変数、関数と同様に名前付きエクスポートとしたり型だけをまとめてエクスポートすることが可能です。
//まとめてエクスポート
export { PI, square, Rectangle, Point, LengthUnit };
//型だけをまとめてエクスポート
export type { Point, LengthUnit };
type
を指定することによって、エクスポートする要素が型であることが明確となります。
また、インポートする際には型として利用されていない場合は TypeScript がエラーを検出します。
同様にインポートもtype
を指定することによって、インポートする要素が型であることを明確化することができます。
//まとめてインポート
import { PI, square, Rectangle, Point, LengthUnit } from "./calc.js";
//型だけをまとめてインポート
import type { Point, LengthUnit } from "./calc";
では、type
を指定したインポートとエクスポートの使用例を確認してみましょう。
cals.ts
では次のようにRectangle
を型としてエクスポートします。
export { PI, square };
export type { Rectangle, Point, LengthUnit };
main.ts
ではRectangle
を型指定せずにインポートします。
import { PI, square, Rectangle } from "./calc.js";
import type { Point, LengthUnit } from "./calc";
calc.ts
から型としてエクスポートされたRectangl
を、main.ts
でインポートしました。
このRectangle
を使って、main.ts
でインスタンス化(実体化)を試みます。
const rect = new Rectangle(5, 10);
→ 'export type' を使用してエクスポートされたため、'Rectangle' は値として使用できません。
calc.ts(15, 15): ここでは 'Rectangle ' がエクスポートされました。
console.log(rect.getArea());
エラーとなりました。Rectangle
は型のみでしか利用することができません。
TypeScript ではインポートして利用するものが、モジュールからどんな状態でエクスポートされているかを把握して、エラーを検出してくれます。すごい。
モジュールとスクリプトによる名前衝突
TypeScript では、import
またはexport
キーワードが含まれるファイルをモジュールとして扱います。
モジュールはグローバルスコープとは別に独自のスコープを持っており、モジュール内部で宣言された関数や変数、クラスは外部からアクセスすることはできません。
export
キーワードを使うことによって、初めて外部からアクセスすることができるようになります。
import
またはexport
キーワードがないファイルはスクリプトとして扱われ、そこで宣言した巻子や変数、クラスはグローバルなものとして扱われます。
const data = "スクリプトAです。";
const data = "スクリプトBです。";
例えば上記のように 2 つのスクリプトファイルがあったとします。どちらもimport
、export
を持っていません。つまりグローバルスコープとして扱われます。
その結果、同じ変数名の変数data
で名前の重複となりエラーとなります。
const data = "スクリプトBです。";
→ ブロック スコープの変数 'data' を再宣言することはできません。ts(2451)
scriptA.ts(1, 7): ここでは 'data' も宣言されました。
import
、export
を持っていないけど、モジュールとして扱いたい場合はexport{}
を記述するとそのファイルはモジュールとして扱われるようになり、名前の重複エラーは発生しません。
const data = "スクリプトBです。";
export {};
Discussion