Typescript学習まとめ

## はじめに
間違っている部分があれば、編集リクエストいただけるとうれしいです！
まだ途中のため、随時更新していくので、通知が欲しい方はいいね！よろしくお願いします。

## Typescriptとは？
静的な型(type)とシステムとクラスベースのオブジェクト指向構文を備えた。Javascriptのスーパセット。Javascript構文の正当な拡張なので、本来のJavascriptのコードがほぼそのままで動作する。

C#やJavaと類似した構文を持つため、これらの言語を利用したことがあればなじみやすい。

Typescriptでは、ECMAScript2015の仕様が取り込まれ、利用できる。
Typescriptを学ぶことで、自然とこれらの次世代構文を学ぶことができる。

## 学習環境

今回は、環境構築の必要なくTypescriptが使える[Typescript Playground](http://www.typescriptlang.org/play/)を使う。

## 変数/データ型

```javascript

// let name: type = initial
// name: 変数の名前
// type: データ型
// initial: 初期値

let hoge: string = 'hoge';
```
Typescriptでは、変数名の後ろにその変数に格納される値の型を指定する。
型を明示した場合、宣言した型と異なる型の値を代入することはできない。

```javascript

let hoge: string = 'hoge';
hoge = 'fuga'; // 文字列は代入することができる
hoge = 9; // エラー
```

## 型を省略する場合
Typescriptでは、変数宣言で型が省略された場合にも、初期値から型を類推する。（**型推論**）


```javascript

let data = 200;
data = 2000;
data = 'hoge'; // エラー
```

変数dataに型を定義せずに初期値として200を代入しているため、number型と見なされる。
よって文字列を代入した場合には、エラーとなる。

#### 型、初期値を省略した場合には、変数はany型と見なされる。

```javascript

let data2;  // any型となる
data2 = 100;
data2 = 'hoge' //エラーなし
```

#### undefined / null を指定した場合

この場合にも、変数にはany型が割り当てられる。

```javascript

let data3 = undefined;  // any型となる
data3 = 100;
data3 = 'data' //エラーなし

let data4 = null;  // any型となる
data4 = 100;
data4 = 'data' //エラーなし
```

> Typescript2.1以降では、any型をただ割り当てるだけでは、ありません。あとで代入された値に基づいて、型が推論されるされるようになっています。（ただし、noImplicitAnyオプションが有功の場合）

## データ型を明示的に変換する「型アサーション」

他の言語で言う所の、「型キャスト」

```javascript

function show(result: string) {
  return `結果は${result}です。`;
}; 
// 引数にstring型の値を受けとる関数を定義


// 数値型を渡すとエラーとなる
console.log(show(100));

// any型に変換
console.log(show(<any>100));

// as構文を使って置き換え
console.log(show('100' as any));
```
手軽に型替えをできるアサーションは、一見して便利に観れるが思わぬエラーの原因にもなるので、利用は最小限に抑えるべき。

## 配列の型定義

```javascript
// let name: type[] = initial
// name: 変数の名前
// type: 配列の要素のデータ型
// initial: 初期値(配列リテラル)

let data: string[] = ['Java', 'Python', 'PHP', 'Ruby', 'C#'];
```

#### Array<type>の形式で表すこともできる

ジェネリックと呼ばれる記法

```javascript
let data: Array<string> = ['Java', 'Python', 'PHP', 'Ruby', 'C#'];
```



#### 多次元配列

次元の数だけ、データ型の後方にブラケットを置くことでデータ型を指定する

```js
let array: number[][] = [[10, 20], [30, 40], [50, 60]];
```

## 連想配列の型定義

```javascript
// let name: { [index: i_type]: v_type } = initial;
// name: 配列名
// i_type: インデックスのデータ型
// v_type: 値のデータ型
// initial: 初期値（オブジェクトリテラル）

let obj: { [index: string]: string } = {
  'name': 'こじろう',
  'name2': 'tom',
  'name3': 'hoge'
};

```

型を定義している{ [index: i_type]: v_type } の部分の記法を、インデックスシグニちゃと言う。

#### interfaceキーワード
インデックスシグニチャは、interfaceキーワードを利用することで、名前付きの型として用意して置くこともできる。何度も利用する場合には、この方法を利用するのが便利。

```javascript
interface StringMap {
  `[index: string]: string;`
}

let obj: StringMap = {
  'name': 'こじろう',
  'name2': 'tom',
  'name3': 'hoge'
};
```

#### 連想配列を利用する場合の注意

```javascript

let obj = {
  'hoge': 'ほげ',
  'foo': 'ふう',
  'bar': 'ばあ'
}

obj.piyo = 'ぴよ'; //　エラー
```

objが作成されたところで、文字列キーを持ったハッシュではなく、「hoge / foo / bar」という文字列型のプロパティを持ったオブジェクト型であると推測される。そのため、変数objにないプロパティ、obj.piyoへのアクセスはエラーになってしまう。

→　連想配列を利用する際には、実質、インデックスシグニチャが必須。

## 列挙型
Typescriptでは他の言語でもよくある、列挙型を利用することができる。

```javascript

enum Sex {
  MALE,
  FEMALE,
  UNKNOWN
}

let m: Sex = Sex.MALE;
console.log(m); // 0
console.log(Sex[m]); // MALE
```

#### 列挙型
**列挙子**　列挙型に属する定数
列挙子には、デフォルトで0,1,2...と数値が割り振られるため、MALE(0:男性)、FEMALE(1:女性)、UNKNOWN(2:不明)という定数をSexという列挙型でまとめたことになる。

```javascript
enum ename { name,... }
  ename:　列挙型の名前
  name: 定数
}
```

## Tuple
複数の異なる型の集合を表現するためのデータ型。
配列のリテラルの形式で[type1, type2, type3...]のように個々の要素の型を表す。

```javascript
let data: [string, number, boolean] = ['hoge', 10.355, false];
console.log(data[0].substring(2)); // 結果 'ge'
console.log(data[1].toFixed(1));  // 結果 10.4
console.log(data[2] === false); // true
```

それぞれの要素の型を認識している。
string / number型のメソッドを呼び出せる。
boolean型の値と比較できる。


二番目の値は、numberなので、data[1].substring(2)のような表記はコンパイルエラーとなる。(number型にsubstringメソッドはないため)

Typescriptを書く場合にタプルを利用することはあまりない。使うべきでない。