Typescripメモ２

## オーバーロード
・関数に対して複数の型を定義すること
・引数や戻り値が異なるが名称が同一なメソッドを複数定義する
・「渡された引数の数によって各パラメータの型が変わる関数」や「パラメータの型によって返り値の型が変わる関数」を表現できる

### 書き方
**・function**
```typescript
function test(arg1:number):number;
function test(arg1:string,arg2:number):string;
//両方の型を満たすように記述
function test(arg1:number | string,arg2?:number) {
    //処理　引数のarg1がnumberの場合かstringによって返す値を変える
}
```
**・type**
```typescript
type Test = {
    (arg1: number): number;
    (arg1: string, arg2: number): string; 
};
const test: Test = (arg1: string | number, arg2?: number) => {
    //処理
};
```

## ジェネリクス
・引数や返り値などの型を任意に設定できる型

### 書き方
```typescript
//「T」の部分にstringなどの型を自由に設定できる
function test<T>(arg: T): T {
      return arg;
}

//複数の場合（T,U,V,T1,T2みたいなのでいい）
function test<T, U, P>(arg1:T, arg2: U): U{
  return arg2
}
```

## クロージャ
・クロージャは内側の関数から外側の関数スコープへのアクセスできる
・関数内などの変数や関数などを他のプログラムから簡単に変更されないように制御できること
・関数内のローカル変数の状態を保持したまま使用することができる

### 書き方
```typescript
function mClosure() {
    //変数resはmClosure関数内でしか参照できない
    var res = 0;
    function closure() {
        return res++;
    }
    return closure;
}
//関数実行でクロージャ生成
var c = mClosure();
//実行するたびに結果を表示
console.log(c());    // 0を出力
console.log(c());    // 1を出力
console.log(c());    // 2を出力

var h mClosure();
console.log(h.res));    //これはエラー
```

## 同期と非同期と並列
**async/await**
async：関数やメソッドに使用するキーワードでPromiseを返却する
await：Promiseに使用するキーワードで結果がでるまで実行を待機する
### 書き方
```typescript
//アロー関数の場合
//asyncを付けて宣言
const test = async() => {
    const req1 = () => {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("1")
                resolve();
            }, 1000);
        });
    }
    const req2 = () => {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log("2")
                resolve();
            }, 1000);
        });
    }

    //awaitを付けて実行
    //awaitはasyncがついている関数内でしか使用できない
    const req1 = await req1();
    const req2 = await req2();
}

//functionの場合
function req1(): Promise<number> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(1);
        }, 1000);
    });
}

function req2(): Promise<number> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(2);
        }, 1000);
    });
}

async funtion test() {
	const req1 = await req1();
	const req2 = await req2();
}
```

**Promise.all**
複数の処理を並列に実行し、全てが完了した後にその終了結果を受け取る
### 書き方
```typescript
async funtion test() {
	const req1 = () => {
	    return new Promise((resolve) => {
	        setTimeout(() => {
	            console.log("1")
	            resolve();
	        }, 1000);
	    });
	}

	const req2 = () => {
	    return new Promise((resolve) => {
	        setTimeout(() => {
	            console.log("2")
	            resolve();
	        }, 1000);
	    });
	}

	const [r1,r2] = await Promise.all([req1,req2);
}
```

## よく見るエラーメッセージ
### Uncaught SyntaxError: Unexpected token 記号
文法エラーで開き括弧が足りないとか、カンマの位置が間違っている場合
変数名や関数名に使用できない記号を使われた場合

### Uncaught SyntaxError: Unexpected end of input
文法エラーで開き括弧に対して閉じ括弧の数があっていない場合

### Uncaught ReferenceError: 変数名や関数名 is not defined
定義されていない変数名や関数名が参照、呼び出した場合

### Uncaught TypeError: Cannot read property ‘プロパティ名’ of undefined
undefinedのプロパティ名にアクセスした場合
オブジェクトの存在しないプロパティの何かにアクセスしている
存在しない配列の場合でもおこる

```
console.log(message.foo.length);
```

上記の場合にオブジェクトmessageにプロパティfooが存在しない
存在しないプロパティを参照しようとしてエラーになる
```
console.log(message.foo);
```

上記のみの場合ならエラーにはならずundefinedが返却される

### Uncaught TypeError: Cannot read property ‘プロパティ名’ of null
nullのプロパティ名にアクセスした場合
上のundefinedと同じようなもの
```
string str = test();　　　　　　//null返却
console.log(str.toString());　 //nullのプロパティ参照してエラーになる
```

### Uncaught TypeError: オブジェクト.メソッド名 is not a function
関数以外のオブジェクトを関数呼び出ししている場合
変数名は関数ではない

```
string str = 'test';
str();//変数は関数じゃない
```