TypeScriptまとめ集
目次
1.クラス化
ECMAScript2015以降より他言語同様クラス化が可能に。
オブジェクト思考言語によくある以下の例を設定できる。
- アクセス修飾子
- getter, setter
- コンストラクター
- 静的メンバー
- 継承
- オーバーライド
- 抽象メソッド
- インターフェイス
など。
アクセス修飾子
アクセス修飾子は以下の3種類
- public...自由にアクセス可能、デフォルトのアクセス修飾子
- protected...同じクラス、または派生クラスのメンバーからアクセス可能
- private...同じクラスからのみアクセス可能
class Sample{
public hello():string{
return `こんにちは、Qiitaさん!`;
}
}
let s = new Sample();
s.hello(); //こんにちは、Qiitaさん!
コンストラクター
インスタンス化をしたと同時に実行される。
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を実装できる
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
静的メンバー
インスタンスを生成しなくてもメソッドを実行できる。
class Sample{
//静的プロパティ
public static name:string = 'Taro';
//静的メソッド
public static hello(name:string):string{
return `こんにちは、${this.name}さん!`;
}
}
let name:string = Sample.name;
Sample.hello(name);
継承
元になるクラスの機能の引き継ぎ、新しい機能の追加、元の機能の一部を修正などができる。
//継承元
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さん。
オーバーライド
継承時、基底クラスで定義済のメソッド/コンストラクターを派生クラスで上書きできる。
class Sample2 extends Sample1{
protected age:number;
//コンストラクターをオーバーライド
constructor(name:string, age:number){
super(name);
this.age = age;
}
//helloメソッドをオーバーライド
hello():string {
return super.hello() + `年齢は${age}ですね?
`;
}
}
抽象クラス、抽象メソッド
派生クラスで機能を上書きすること前提にする。
//抽象クラスを宣言
abstract class Sample1 {
abstract hello():string;
}
//継承先
class Sample2 extends Sample1{
hello():string{
return `こんにちは、${this.name}さん!`;
}
}
インターフェイス
すべてのメソッドが抽象メソッドであり、複数のインターフェイスを同時に継承することが可能。
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}さん。`;
}
}
インターフェイスを継承して、新しいインターフェイスを宣言することもできる
interface Interface1 extends Interface2{ ...}
2.モジュール化
モジュールとは?
- 機能ごとにファイルを分割してまとまりを持った処理を作る。
- 1モジュールに対して1ファイルが基本。
- 代表的なモジュールシステムはCommonJSとES Moduleの2種類の方式がある。
- CommonJSはサーバー用、ES Moduleはブラウザ用で分けると良い。
- ES ModuleはECMA Script6で追加されたため、古いブラウザだと使えない可能性があるため注意。
モジュールの定義
- CommonJSでは、module.exportsで定義する。
- ES Moduleでは、exportをつけて定義できる。
CommonJSの場合
//関数のモジュール化
module.exports= function showMessage():void {
console.log(`ようこそ、Qiita!`);
}
//クラスのモジュール化
class Util {
static getVersion():string{
return '1.0.0';
}
}
module.exports = Util;
ES Moduleの場合
//これは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の場合
//インポートするモジュールを選択する
let a = require('Util');
let b = require('showMessage');
//インポートした関数を使用する
a.showMessage();
console.log(b.Util.getVersion());
ES Moduleの場合
//インポートするモジュールを選択する
//from ~ は相対パスから拡張子を取り除いた形式で表す
import { showMessage, Util } from './App';
//インポートした関数を使用する
showMessage();
console.log(Util.getVersion());
モジュール配下のメンバーに別名を付与したい場合
//別名を定義
import { showMessage as myMessage, Util as MyUtil } from './App';
//インポートした関数を使用する
myMessage();
console.log(MyUtil.getVersion());
モジュール配下のメンバーを全てインポートしたい時
//「*」で全てインポートできる
//as区で別名を定義すること
import * as aaa from './App';
//インポートした関数を使用する
aaa.showMessage();
console.log(aaa.Util.getVersion());
既定のエクスポートをインポート
モジュール配下の一つのメンバーに対してdefaultキーワードを付与することで、インポート時に関数/クラスの名前を指定する必要をなくすことができる。
export default class {
static getVersion():string{
return '1.0.0';
}
}
//import側
import app from './App';
console.log(app.getVersion());
任意のタイミングでモジュールをインポートする(遅延インポート、動的インポート)
今までの静的インポートと言う。
//Promiseオブジェクトを生成
import('./App')
.then(app => {
app.showMessage();
});
//async関数
async function main(){
let app = await import('./App');
app.showMessage();
}
再エクスポート
//Hoge/Fooモジュール指定されたメンバーを再エクスポート
export { HogeUtil } from './Hoge';
export { FooUtil } from './Foo';
//Barモジュールすべてのメンバーを再エクスポート
export * from './Bar';
名前空間
モジュールのさらに上の階層を定義して、インポート・エクスポートするモジュールをまとめる。
古い言い方だと、内部モジュールという。(外部モジュールは普通のやつ)
//namespaceを宣言する
namespace MainApp{
export class Hoge { ... }
export function too() { ... }
}
//名前空間配下のクラス・関数を呼び出し
let mah = new MainApp.Hoge();
MainApp.foo();
名前空間自体に階層儲けることも可能
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 { ... }