3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TypeScript まとめ3(モジュール化)

Last updated at Posted at 2021-04-30

TypeScriptまとめ集

  1. 型について
  2. ユーティリティ型
  3. モジュール化
  4. インストール〜コンパイル方法

目次

  1. クラス化
  2. モジュール化
  3. デコレーター

1.クラス化

ECMAScript2015以降より他言語同様クラス化が可能に。

オブジェクト思考言語によくある以下の例を設定できる。

  • アクセス修飾子
  • getter, setter
  • コンストラクター
  • 静的メンバー
  • 継承
  • オーバーライド
  • 抽象メソッド
  • インターフェイス
    など。

アクセス修飾子

アクセス修飾子は以下の3種類

  • public...自由にアクセス可能、デフォルトのアクセス修飾子
  • protected...同じクラス、または派生クラスのメンバーからアクセス可能
  • private...同じクラスからのみアクセス可能
typescript(アクセス修飾子)
class Sample{

  public hello():string{
    return `こんにちは、Qiitaさん!`;
  }
}

let s = new Sample();
s.hello();  //こんにちは、Qiitaさん!

コンストラクター

インスタンス化をしたと同時に実行される。

typescript(コンストラクター)
class Sample{

  private name:string;

  constructor(name:string){
    this.name = name;
  }
  //コンストラクターは以下のように書くこともできる
  //コンストラクターの引数にアクセス修飾子を付与する
  constructor(private name:string){}

  public hello():string{
    return `こんにちは、${this.name}さん!`;
  }
}

let s = new Sample('Taro');
s.hello();  //こんにちは、Taroさん!

getter, setter

  • getブロックでgetterを実装できる
  • setブロックでsetterを実装できる
typescript(getter,setter)
class Sample{

  private _name!:string;

  //getter
  get name():string{
    return this._name;
  }

  //setter
  set name(value:string){
    this._name = value;
  }
}

let s = new Sample();
s.name = 'Taro';
console.log(s.name); //結果:Taro

静的メンバー

インスタンスを生成しなくてもメソッドを実行できる。

typescript(静的メンバー)
class Sample{
  //静的プロパティ
  public static name:string = 'Taro';

  //静的メソッド
  public static hello(name:string):string{
    return `こんにちは、${this.name}さん!`;
  }
}

let name:string = Sample.name;
Sample.hello(name)

継承

元になるクラスの機能の引き継ぎ、新しい機能の追加、元の機能の一部を修正などができる。

typescript(継承)
//継承元
class Sample1{
  protected name:string;

  constructor(name:string){
    this.name = name;
  }

  hello():string{
    return `こんにちは、${this.name}さん!`;
  }
}

//継承先
class Sample2 extends Sample1{
  //派生クラス独自のメソッドを定義
  bye():string{
    return `さようなら、${this.name}さん。`;
  }
}

let s = new Sample2('Taro');
s.hello();  //こんにちは、Taroさん!
s.bye();    //さようなら、Taroさん。

オーバーライド

継承時、基底クラスで定義済のメソッド/コンストラクターを派生クラスで上書きできる。

typescript(オーバーライド)
class Sample2 extends Sample1{
  protected age:number;
  
  //コンストラクターをオーバーライド
  constructor(name:string, age:number){
    super(name);
    this.age = age;
  }

  //helloメソッドをオーバーライド
  hello():string {
    return super.hello() + `年齢は${age}ですね?
`; 
  }
}

抽象クラス、抽象メソッド

派生クラスで機能を上書きすること前提にする。

typescript(抽象クラス、抽象メソッド)
//抽象クラスを宣言
abstract class Sample1 {
  abstract hello():string;
}

//継承先
class Sample2 extends Sample1{
  hello():string{
    return `こんにちは、${this.name}さん!`;
  }
}

インターフェイス

すべてのメソッドが抽象メソッドであり、複数のインターフェイスを同時に継承することが可能。

typescript(インターフェイス)
interface Sample1{
  name:string;  
  hello():string;
}
  
interface Sample2{
  bye():string
}
  
class Sample3 implements Sample1,Sample2{
  
  name:string;
    
  constructor(name:string){
      this.name = name;
  }   
  hello():string{
    return `こんにちは、${this.name}さん!`;
  }
  bye():string{
    return `さようなら、${this.name}さん。`;
  }
}

インターフェイスを継承して、新しいインターフェイスを宣言することもできる

typescript(interfaceの継承)
interface Interface1 extends Interface2{ ...}

2.モジュール化

モジュールとは?

  • 機能ごとにファイルを分割してまとまりを持った処理を作る。
  • 1モジュールに対して1ファイルが基本。
  • 代表的なモジュールシステムはCommonJSES Moduleの2種類の方式がある。
  • CommonJSはサーバー用、ES Moduleはブラウザ用で分けると良い。
  • ES ModuleはECMA Script6で追加されたため、古いブラウザだと使えない可能性があるため注意。

モジュールの定義

  • CommonJSでは、module.exportsで定義する。
  • ES Moduleでは、exportをつけて定義できる。

CommonJSの場合

typescript(CommonJSでのモジュール定義)
//関数のモジュール化
module.exports= function showMessage():void {
  console.log(`ようこそ、Qiita!`);
}

//クラスのモジュール化
class Util {
  static getVersion():string{
    return '1.0.0';
  }
}

module.exports = Util;

ES Moduleの場合

typescript(ESModuleでのモジュール定義)
//これはexportがついていないため、アクセスできない
const TITLE:string = 'Qiita';

//関数のモジュール化
export function showMessage():void{
  console.log(`ようこそ、${TITLE}!`);
}

//クラスのモジュール化
export class Util {
  static getVersion():string{
    return '1.0.0';
  }
}

//------------------------------------------
//別の書き方も可能
class Util { ... }

//そのままエクスポート
export { Util };

//リネームしてエクスポート
export { Util as AppInfo };

モジュールのインポート

  • 別ファイルで定義したモジュールを使用することができる。(インポート)
  • CommonJSでは、requireをつけて定義する。
  • ES Moduleでは、importをつけて定義できる。

CommonJSの場合

typescript(CommonJSでのインポート)
//インポートするモジュールを選択する
let a = require('Util');
let b = require('showMessage');

//インポートした関数を使用する
a.showMessage();
console.log(b.Util.getVersion());

ES Moduleの場合

typescript(ESModuleでのインポート)
//インポートするモジュールを選択する
//from ~ は相対パスから拡張子を取り除いた形式で表す
import { showMessage, Util } from './App';

//インポートした関数を使用する
showMessage();
console.log(Util.getVersion());

モジュール配下のメンバーに別名を付与したい場合

typescript(モジュールのインポート(別名))
//別名を定義
import { showMessage as myMessage, Util as MyUtil } from './App';

//インポートした関数を使用する
myMessage();
console.log(MyUtil.getVersion());

モジュール配下のメンバーを全てインポートしたい時

typescript(モジュールのインポート(全て))
//「*」で全てインポートできる
//as区で別名を定義すること
import * as aaa from './App';

//インポートした関数を使用する
aaa.showMessage();
console.log(aaa.Util.getVersion());

既定のエクスポートをインポート
モジュール配下の一つのメンバーに対してdefaultキーワードを付与することで、インポート時に関数/クラスの名前を指定する必要をなくすことができる。

typescript(既定のエクスポートをインポート)
export default class {
  static getVersion():string{
    return '1.0.0';
  }
}

//import側
import app from './App';

console.log(app.getVersion());

任意のタイミングでモジュールをインポートする(遅延インポート、動的インポート)
今までの静的インポートと言う。

typescript(遅延インポート)
//Promiseオブジェクトを生成
import('./App')
  .then(app => {
    app.showMessage();
  });

//async関数
async function main(){
  let app = await import('./App');
  app.showMessage();
}

再エクスポート

typescript(再エクスポート)
//Hoge/Fooモジュール指定されたメンバーを再エクスポート
export { HogeUtil } from './Hoge';
export { FooUtil } from './Foo';

//Barモジュールすべてのメンバーを再エクスポート
export * from './Bar';

名前空間

モジュールのさらに上の階層を定義して、インポート・エクスポートするモジュールをまとめる。
古い言い方だと、内部モジュールという。(外部モジュールは普通のやつ)

typescript(名前空間)
//namespaceを宣言する
namespace MainApp{
  export class Hoge { ... }
  export function too() { ... }
}

//名前空間配下のクラス・関数を呼び出し
let mah = new MainApp.Hoge();
MainApp.foo();

名前空間自体に階層儲けることも可能

typescript(階層付き名前空間)
namespace Wings.MainApp{
  export class Hoge{}
  export function foo() {}
}
let wmah = new Wings.MainApp.Hoge();
Wings.MainApp.foo();

//以下のような書き方も可能
namespace Wings{
  export namespace MainApp{
    export class Hoge{}
    export function foo(){}
  }
}

3.デコレーター

デコレーターとは

クラスやプロパティ、メソッド、引数などに対して付与できる一種の修飾子。

例:Angularの場合

デコレーターの例
//以下の書き方で、<my-app>要素がAppComponentクラスで処理される、という意味になる
@Component({
  selector:'my-app',
  templateUrl:'./app.html',
  styleUrls:['./app.css]
})

export class AppComponent {...}

デコレーターの一般的な記法

@name(args, ...)
・name: デコレーター名
・args: 任意の引数
  • 複数のデコレーターを列挙することも可能
    この場合myMethod2を@deco1デコレーター、@deco2デコレーターで就職していることとなる
    @deco1
    @deco2
    myMethod(){ ... }

デコレーターを定義してみる

自分でデコレーターを定義してみることも可能。
下記は一例。

デコレーターの定義
//logデコレーターを宣言
function log(target: any, key: string, desc: PropertyDescriptor){

  //オリジナルのメソッドを退避
  let origin = desc.value;

  //メソッドの書き換え
  desc.value = function(){

    //元メソッドの実行前に行う処理
    console.log(`${key} start...`);
    let start = Date.now();

    //元メソッドを実行
    let result = origin.apply(this, arguments);

    //元メソッドの実行後に行う処理
    let end = Date.now();
    console.log(`${key} end...`);
    console.log(`Process Time ${end - start}ms`);

    //元のメソッドの戻り値を返す
    return result;
  }
}

デコレーターの利用

上記で定義した@logデコレーターを利用する場合...

class MyClass{
  @log
  test():string{
    return 'TEST';
  }
}

let c = new MyClass();
c.test();

ちなみに、デコレーターは引数付きでも定義が可能

引数付きデコレーターの利用
//定義
function log(tag: string) { ... }

//利用
@log('TEST')
test():string { ... }
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?