【初心者】TypeScript文法を理解していくvol.2

## はじめに
引き続き、Typescriptを学んでいく

## 配列の型定義
定義の仕方は2種類存在する
```.ts
const members: string[] = ["Ryoma", "Yuta"];
const friends: Array<string> = ["Taro", "Jiro"];
```
### アノテーションしなくても型推論される
どんな値が代入可能かを指定することができる。

```.ts
// 文字が入ると予測できる
const fruits = ["Apple"];
fruits.push("Orange");
```

## タプル
厳密な配列を定義できる
- 配列の要素数
- 順番
- 型

```.ts
// 要素数3つ・数字、文字、真偽値の順番
let response: [number, string, boolean];
response = [200, "OK", true];
```

### ラベルをつける
可読性を高めるラベル

```.ts
// [1, "email"] これは何の型なのかを補ってくれる
const property: [id: number, name: string] = [1, "email"]
```
可変長引数にも使える（レストパラメーターというらしい）

```.ts
let cacheControl: [boolean, ...string[]];
cacheControl = [false, "max-age=0"];
cacheControl = [true, "max-age=86400", "must-revalidate"];
```

## オブジェクトの型定義
object型は、伝えるだけなのでanyと大差はない

**小文字object型**
```.ts
// 　プリミィティブ型は代入できない
const obj: object = {
    companyName: "abc株式会社",
    email: "abc@gmail.jp",
}
obj = 1; // できない
obj = ture; // できない
```
**大文字Object型**
- プロパティを持つ値なら何でも代入できる。
```.ts
let a: Object;
a = {}; // 可能
a = true;

a = null; // できない
a = undefined; // できない
```

オブジェクトリテラル表記でkeyとvalueを明確化する
```.ts
const company: {
    companyName: string
    email: string
  } = {
    companyName: "toraco株式会社",
    email: "corp@toraco.jp",
  }
  console.log(company.email)
```

### オプショナル表記
- ?のついたプロパティはあってもなくてもok

```.ts
const user: {
    email?: string
    firstName: string
    lastName: string
  } = {
    // emailはなくても良い
    firstName: "Takaaki",
    lastName: "Inagaki"
  };
```

### ReadOnly修飾子のついたプロパティ

下の例で言うと、`post.id`は上書きできないです
```.ts
const post: {
    readonly id: number
    title: string
  } = {
    id: 1234,
    title: "TypeScript初級"
  }
  post.title = "TypeScript中級"
  // post.id = 5678 上書きできない
```

## インデックスシグネーチャー
`[key: T]: U`のような構造をインデックスシグネチャと呼ぶ

```.ts
// 文字列型の値とkeyを持つように整理
const cells: {[key: string]: string} = {
    A1: "name",
    A2: "price",
  }
  cells.B1 = "キャンディ"
  cells.B2 = "150円"
```
エラーコードとかまとめるのもありかもしれん
```.ts
const errorCode: {[key: number]: string} = {
    400: "Bad Request",
    401: "Unauthorized",
    403: "Forbidden",
    404: "Not Found",
  }
```
## 型エイリアス
使い回しができる
これはめちゃくちゃ便利

```.ts
type Country = {
    capital: string
    language: string
    currency: string
}

const Japan: Country = {
    capital: "Tokyo",
    language: "Japanese",
    currency: "Yen"
}
```
### 型を合併したり交差させたりもできる

```共通.ts
type Worrier = {
    attack: number
    hp: number
    mp: number
}
type Magician = {
    magic_attack: number
    hp: number
    mp: number
}
```

```合併.ts

type Knight = Worrier | Magician
const knight: Knight = {
    attack: 20,
    hp: 100,
    mp: 0
}
```
```交差.ts
type Paladin = Worrier & Magician
const paladin: Paladin = {
    attack: 10,
    magic_attack: 10,
    hp: 100,
    mp: 50
}
```

## 配列ループ
```definition.ts
// 型定義
type CartItem = {
    name: string
    price: number
    quantity: number
}
// 再利用可能に
type Cart = CartItem[];

//　代入
const cart: Cart = [
    {
      name: "キャンディ",
      price: 150,
      quantity: 2
    },
    {
      name: "クッキー",
      price: 200,
      quantity: 1
    },
    {
      name: "チョコレート",
      price: 300,
      quantity: 1
    },
]
```

```ループ.ts
// for-of文を使用
for(const cartItem of cart){
    console.log(cartItem.name)
};

// forEach() はループ処理内で
cart.forEach((cartItem: CartItem) => {
    console.log(cartItem.name)
});

// mapメソッドで新しい配列を作成し、そこに返す
const snackNames = cart.map(cartItem => {
    return cartItem.name
});

// filterメソッドで条件にマッチした要素の配列を返す
const luxurySnacks = cart.filter(cartItem => {
    return cartItem.price >= 200
});

// reduce() はループごとに前回の値を参照して次のループに渡すことができる
const total = cart.reduce((prev: number, cartItem: CartItem) => {
  return prev + cartItem.price * cartItem.quantity
}, 0)
```
## オプションパラメータとデフォルトパラメータ

2種類存在します
- `building?: string`
- `building = ""`



```.ts
const registerAddress = (prefecture: string, city: string, street: string, building?: string): void => {
    let address = prefecture + city + street
    console.log(address)
  }
  registerAddress("東京都", "千代田区", "千代田1-1")
  registerAddress("東京都", "千代田区", "千代田1-1", "皇居")

// オプションパラメーターにデフォルト値を指定することができる
const registerAddressWithDefault = (prefecture: string, city: string, street: string, building = ""): void => {
    const address = prefecture + city + street + building
    console.log(address)
  }
```


## おわりに
もりもりになってしまいましたが、少しずつ学んでいきます。Typescript面白い！