TypeScript入門

# はじめに
私は普段フロントエンドエンジニアとして開発しながら働いています。
TypeScriptの基礎について備忘録的に残しておきたいと思います。

# この記事の対象者
* JavaScriptの次にTypeScriptを学びたい人
* TypeScriptの型定義について学びたい人

# TypeScriptとは
TypeScriptはJavaScriptを拡張した言語になります。
従来のJavaScriptでは型が`any`でしたが、品質の向上が求められ、型定義を用いるTypeScriptが使われるようになりました。


# 主なデータ型の種類
```tsx
// string型
const name: string = "Taro"; 

// number型
const age: number = 1; 

// boolean型
const flg: boolean = true; 

// arrayのstring型
const array: string[] = ["apple", "banana", "grape"];

```
`:`の後に明示的に型を定義することを「アノテーション」と呼びます。


# 型推論
TypeScriptでは上記のようにアノテーションを使わなくても自動で型をつけてくれます。これを型推論といいます。
```tsx
let name = "Taro"; // string型

// Bad：nameはstring型のため代入できない
name = 1; 

// Good：string型のため代入できる
name = "Ken"; 
```

# 配列の型定義
```tsx
// number型のみ許容する配列
const array1: number[] = [1, 2, 3];

// number型 or string型のみ許容する配列
const array2: (number | string)[] = [1, 2, "hoge"]; 
```


# interface
オブジェクトの型定義はinterfaceを使います。
```tsx
interface PROFILE {
  name: string;
  age?: number;
}

const person1: PROFILE = {
  name: "Taro",
  age: 22,
}; 
```
上記の`age`のようにオブジェクト要素に後ろに「?」を付与することでプロパティを任意にすることもできます。
```tsx
// 'age'要素がなくてもOK
const person2: PROFILE = {
  name: "Kenji",
}; 
```


# Intersection Types
複数の型を結合した型をIntersection Typesと言います。
下記だと`STAFF`が該当します。
```tsx
type PROFILE = {
  name: string;
  age: number;
};

type JOB = {
  office: string;
  category: string;
};

type STAFF = PROFILE & JOB;

const personA: STAFF = {
  name: "Jiro",
  age: 29,
  office: "Tokyo",
  category: "Engineer",
};
```


# Union Types
|（パイプ）を用いることで2つ以上の型を使うことができます。
```tsx
let value: string | null = "hoge";

// Good
value = "test";

// Good
value = null;

// Bad
value = 1;
```

# Literal Types
代入可能な値を明示的に型にすることもできます。
```tsx
let fruits: "apple" | "banana" | "grape";

// Good
fruits = "apple";

// Bad
fruits = 'melon'
```


# typepf
宣言済みの変数などから型を継承したい場合はtypeofを使います。
```tsx
let message: string = "Hoge";

// string型を継承
let newMessage: typeof message = "HogeHoge";

// Bad
newMessage = 1;
```


# keyof
オブジェクトの型からプロパティ名（キー）を型とするのがkyeofになります。
```tsx
type KEYS = {
  first: string;
  second: string;
};

let value: keyof KEYS;

value = "first";

// Bad
value = "third";
```

# enum
列挙型はenumを使います。
下記だと`SOCCER`に0、`BASEBALL`に1が割り当てられます。
enumを用いることで可読性が高まり、メンテナンスしやすくなります。
```tsx
enum SPORTS {
  SOCCER,
  BASEBALL,
}

interface STUDENT {
  name: string;
  club: SPORTS;
}

const studentA: STUDENT = {
  name: "Ken",
  club: SPORTS.BASEBALL,
};
```

# Generics
Genericsを用いることで使用する度に型を宣言することができます。
同じようなコードを別の型で繰り返す場合などに役立ちます。
慣習的に`T`などが使われることが多いです。
```tsx
interface GEN<T> {
  msg: T;
}

const gen1: GEN<string> = { msg: "hoge" };
const gen2: GEN<number> = { msg: 2 };

```
デフォルトの型を定義すると`<string>`などの宣言がなくても大丈夫です。
```tsx
interface GEN<T = string> {
  msg: T;
}

const gen1: GEN = { msg: "hoge" };

```

また`extends`を併せて用いることで使用できる型を制限することができます。
```tsx
interface GEN<T extends string> {
  msg: T;
}

// Good
const gen1: GEN<string> = { msg: "hoge" };

// Bad
const gen2: GEN<number> = { msg: 2 };

```
関数で使う場合
```tsx
function func<T>(value: T) {
  return value;
}

func<string>("hello");
func<number>(123);
func<null>(null);

```
関数で`extends`を使う場合
```tsx
function func<T extends string>(value: T) {
  return value;
}

// Good
func<string>("hello");

// Bad
func<number>(123);
```
interfaceと併せて使う場合
```tsx
interface Props {
  name: string;
}

function func<T extends Props>(value: T) {
  return value;
}

func({name:'Taro'});
```

# 最後に
いかがだったでしょうか。
今回はTypeScriptの基礎についてご紹介しました。
少しでもお役に立てれば幸いです。

# 参考
* [サバイバルTypeScript](https://typescriptbook.jp)
* [最速で学ぶTypeScript](https://www.udemy.com/course/typescript-react-frontend/)