TypeScriptを息を吸う如く書けるようになりたい【基礎①】

TypeScriptではさまざまな型の定義方法があります。
この記事ではTypeScriptにおける型定義を学習記録としてライトにまとめたものです。

:::note warn
独自の持論すぎるのでそれは違うだろう！って感じた人は頭の中から消し去ってください！
:::

TypeScriptが何か？などの概要は割愛させていただきたいと思います。
TypeScriptについて概要が知りたい方は過去の記事をご覧いただければと思います。

https://qiita.com/tanimoto-hikari/items/984cc2a7205a121380da

また、もっと詳しく書いてある記事を読みたい方は下記の記事をご覧ください！

https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a

:::note info
【この記事をオススメしたい人】
・TypeScriptを学習している人
・TypeScriptの型定義の熟練度を上げたい人！
:::

## `Union型`の注意点
定義する順番によってエラーになることがあります。
```typescript
let union: number | string = 3;
union.toUppercase();
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/d1546c71-d6dd-99b8-f148-417e266c5cfd.png)
上記のようにunionに文字列が入っていない状態で文字列に対して利用できるメソッドを利用するとエラーになります。
当然と言えば当然ですが…。

## `Literal型`
typeScriptは`const`で定義することで`literal型`となります！
```typescript
// literal型で定義される
const test = 'test';

// string型で定義される
let test = 'test';
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/19816020-a635-d93c-5b41-d958a971c549.png" width="100%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/f6d50c3e-68a1-1cee-95f0-cadcd53c9db3.png" width="100%">

## `Enum型(列挙型)`と`Union・Literal型`
`Enum型`を利用した型定義は、`Union型`と`Literal型`のを組み合わせても同じような定義ができます。
また、typeエイリアスを使うことで`Union型`と`Literal型`のを組み合わせはスッキリさせることができます！

```typescript
// Enum型での定義
enum DrinkSize {
  SMALL = 'SMALL',
  MEDIUM = 'MEDIUM',
  LARGE = 'LARGE',
}

// Union型とLiteral型の組み合わせ
const drink: {
  size: 'small' | 'medium' | 'large';
} = {
  size: 'small',
}

// typeエイリアスを使う
type DrinkSizes = 'small' | 'medium' | 'large';
const drink: {
  size: DrinkSizes;
} = {
  size: 'small',
};
```

`enum型`で定義するとオブジェクトなので`DrinkSize.SMALL`で呼び出すことができます。

:::note info
`enum型`の定義は基本的に大文字、今回DrinkSizeとした名前の部分はパスカルケースを利用するのが一般的です！
:::

ケースバイケースだと思いますが、数が少ない場合`Enum型`で定義すると少し冗長な感じがするので`Union・Literal型`の組み合わせで定義するというのも良いという意見もあります。

個人的にはチームで統一する方がいいかな…と思ったりもしますが、どちらがいいんでしょうね…
ここに関しては知見がないので勉強ですね…。

### 【補足】`emau型`で｀=`の右側を指定しなかった場合
下記のように`=`の右側を記述しなかった場合は自動で数値がセットされます。

```typescript
enum DrinkSize {
  SMALL,
  MEDIUM,
  LARGE,
}
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/fcd34115-fc4b-c339-c2d5-43c7da5baadc.png" width="100%">
MEDIUMに数値をセットした場合は、次に定義したものは＋1されてセットされます。

```typescript
enum DrinkSize {
  SMALL,
  MEDIUM = 100,
  LARGE,
}
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/156ede0e-1b62-0ac1-94dc-fadb97262553.png" width="100%">

:::note info
日本語文字を右側に指定するよりも、何も指定せずに数値として扱われた方がメモリの節約にになるとされているので特にこだわりたい部分がない場合は`=`の右側を指定しない方が良いと思われます。
:::

## 関数の戻り値にも型定義する
基本的には関数の返り値にも方を定義して予期せぬ値が返ってきてもエラーが出るようにしておいた方がいいかと思います。

返り値の型定義は画像のフォーカスされた箇所に指定します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/2c27c7be-a135-3343-06d1-95a532c7afa9.png" width="100%">
型が指定してあると下記の画像のようにnumber型以外が返されようとした場合にエラーを出してくれます！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/1550e978-9f2e-c868-4fc8-fbdf8e9273c3.png" width="100%">


## 戻り値がない関数の型定義に`undefind型`は基本使わない。`void型`を使う

関数は`void型`で定義してもundefindを返します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/ae2a016f-7b42-58b3-bb22-69fc2f3960e8.png" width="100%">

なら`undefined型`にしちゃえばいいのでは？と考えます。
ただ、`undefined型`を利用するにはreturnが必須になります。
```typescript
// voide型
function sum(): void {
  console.log('test');
}

// undefined型
function sum(): undefined {
  console.log('test');
  return;
}
```
なので戻り値がない関数を定義する時は`void型`が一般的です。

https://typescriptbook.jp/reference/functions/void-type