TypeScriptにおける「export」キーワード:クラスとインターフェースを公開する詳細ガイド
TypeScriptにおける「export」キーワード:クラスとインターフェースを公開する理由
TypeScriptで「export」キーワードを使用するのは、モジュールシステムにおける情報カプセル化とコードの再利用性を実現するためです。具体的には、以下の2つの役割を果たします。
クラスとインターフェースの公開範囲を制御する
- デフォルトの公開範囲
export
キーワード単独で使用すると、そのモジュールのみから直接アクセスできるようになります。他のモジュールからは、import ステートメントを利用して明示的にインポートする必要があります。 - publicキーワードとの組み合わせ
export
キーワードとpublic
キーワードを組み合わせることで、そのモジュール内からクラスやインターフェースにアクセスできるようにします。
例:public
キーワードとの組み合わせ
export class Person {
public name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public introduce() {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
この例では、Person
クラスは export
と public
キーワードの組み合わせにより、そのモジュール内のどこからでもアクセスできるようになっています。
例:export
キーワード単独の使用
export class Point {
private x: number;
private y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
public getX(): number {
return this.x;
}
public setX(x: number): void {
this.x = x;
}
public getY(): number {
return this.y;
}
public setY(y: number): void {
this.y = y;
}
}
この例では、Point
クラスは export
キーワードのみを使用しているため、そのモジュールから直接アクセスすることはできません。他のモジュールからは、import ステートメントを使って明示的にインポートする必要があります。
import { Point } from './point'; // モジュールパスを指定してインポート
const point = new Point(10, 20);
console.log(`x: ${point.getX()}`); // getX() メソッドを呼び出す
point.setX(30);
console.log(`x: ${point.getX()}`); // 座標値を変更
コードの再利用性を高める
- モジュールの公開APIを明確にすることで、他の開発者がコードを理解しやすくなります。
- 異なるモジュール間でクラスやインターフェースを共有することで、重複開発を削減し、コードの保守性を向上させることができます。
例:異なるモジュール間でのクラス共有
モジュールAで定義された Person
クラスを、モジュールBで使用する場合:
モジュールA (person.ts)
export class Person {
// ... (Person クラスの定義)
}
モジュールB (main.ts)
import { Person } from './person'; // モジュールAからPersonクラスをインポート
const person = new Person('Taro', 30);
console.log(`氏名: ${person.name}`);
console.log(`年齢: ${person.age}`);
このように、export
キーワードを使用してクラスやインターフェースを公開することで、TypeScriptにおけるモジュールシステムの利点を最大限に活用することができます。
export
キーワード単独で使用すると、そのモジュールから直接アクセスすることはできませんが、import ステートメントを使って明示的にインポートできます。public
キーワードと組み合わせることで、そのモジュール内からどこからでもアクセスできるようになります。- TypeScriptにおける
export
キーワードは、クラスやインターフェースの公開範囲を制御し、コードの再利用性を高めるために重要です。
// person.ts
export class Person {
public name: string;
private age: number; // 年齢は非公開
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public introduce() {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
public getAge(): number { // 年齢を取得するメソッド (公開)
return this.age;
}
}
例 2:export
キーワード単独で公開されたインターフェース
// shape.ts
export interface Shape {
draw(): void;
}
// circle.ts
import { Shape } from './shape';
export class Circle implements Shape {
private radius: number;
constructor(radius: number) {
this.radius = radius;
}
public draw(): void {
console.log(`Draw a circle with radius: ${this.radius}`);
}
}
export class Person {
public name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public introduce() {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
import { Person } from './person'; // モジュールAからPersonクラスをインポート
const person = new Person('Taro', 30);
console.log(`氏名: ${person.name}`);
console.log(`年齢: ${person.age}`);
person.introduce(); // モジュールAのメソッドを呼び出す
セブンセグメント宣言
declare module "my-module" {
export class Person {
public name: string;
public age: number;
constructor(name: string, age: number);
public introduce(): void;
}
export interface Shape {
draw(): void;
}
}
利点
- コードエディターのIntelliSense 機能を向上させることができます。
- 外部モジュールからインポートされたクラスやインターフェースに対して型定義を提供することができます。
欠点
- モジュールの内部実装を公開することになります。
- 実際にクラスやインターフェースを実装する必要があるため、コード量が増えてしまいます。
プライベートモジュール
// my-module.d.ts
declare module "my-module" {
export class Person {
public name: string;
public age: number;
constructor(name: string, age: number);
public introduce(): void;
}
export interface Shape {
draw(): void;
}
}
// my-module.ts
module myModule {
export class Person {
public name: string;
private age: number; // 年齢は非公開
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public introduce() {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
public getAge(): number {
return this.age;
}
}
export interface Shape {
draw(): void;
}
export class Circle implements Shape {
private radius: number;
constructor(radius: number) {
this.radius = radius;
}
public draw(): void {
console.log(`Draw a circle with radius: ${this.radius}`);
}
}
}
- プライベートな実装を隠蔽することができます。
- コードを分割し、モジュール間の依存関係を明確にすることができます。
- TypeScript コンパイラの設定が必要になります。
- 複数のファイルを使用する必要があるため、コード管理が煩雑になる可能性があります。
アンビエント宣言
/// <reference path="my-module.d.ts" />
import { Person, Shape } from 'my-module';
const person = new Person('Taro', 30);
console.log(`氏名: ${person.name}`);
console.log(`年齢: ${person.age}`);
person.introduce();
const circle = new Shape();
circle.draw();
- コード量を削減することができます。
- 外部モジュールの型情報のみを利用したい場合に有効です。
- モジュールの内部実装が不明になる可能性があります。
- 実際にクラスやインターフェースを実装する必要はありませんが、型定義が不完全な場合、コンパイルエラーが発生する可能性があります。
- プライベートモジュール: コードを分割し、モジュール間の依存関係を明確にする際に有効です。
- セブンセグメント宣言: 外部モジュールに対して型定義を提供する際に有効です。
export
キーワード: 最も一般的で、シンプルに使用できる方法です。
どの方法を選択するかは、状況や目的によって異なります。それぞれの特徴を理解し、適切な方法を選択してください。
- 最新の情報については、TypeScript の公式ブログやリリースノートもチェックしてみてください。
typescript module public