ザッとTypescriptまとめてみた

#記事を書くきっかけ
Typescriptの基礎についてザッと勉強したのでまとめようと思います。
今回は以下の動画教材で勉強しました。
[最速で学ぶTypeScript](https://www.udemy.com/share/103jMO3@Aif_smL1n7OTepF5eV8qs9LPLrBGtILJjPi4vcgCmKTKG3HVw6gPQG8vIv7anQwadg==/)

#目次
- Typescript概要
- 型定義
  - 型の基本形
  - 配列
  - オブジェクト
  - 関数
  - type
  - enum
  - Generics
- まとめ
- 参考
 

#概要
・2012年にマイクロソフト社が開発したAltJSの1つ
&emsp;AltJS：Alternative JavaScript (JavaScriptより効率的に開発でき、かつコンパイルすると
&emsp;&emsp;&emsp;&emsp;&emsp;JavaScriptのコードが生成されるプログラミング言語)
・型を指定する静的型付け言語
・最終的にJavaScriptにコンパイル(変換)される

#型定義
Typescriptの型付けには
・明示的に型を指定する方法
&emsp;(`：型`で指定)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091770/b5118873-1c56-193f-dc5d-291c46b20f77.png" width="400px">
・型推論によって明示せず型を指定する方法
&emsp;(変数名をhoverすると表示される)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2091770/a4e6f3a4-9fdc-e256-5e91-4a2911d1e244.png" width="300px">

の2種類がある。

##型の基本形
Typescriptの基本的な型は以下の3つ。（プリミティブ型）
number：数値
string：文字列
boolean：真偽値

```TS:typescript.ts
let name:string = "hello";
let num:number = 1;
let bool:boolean = true;
```
anyを使用するとJavascriptのようになんでも入れることができる。
が、型のチェックの放棄をしているので乱用するのはNG。

```TS:typescript.ts
let a:any = "hello";
a = 1;
```

###配列
配列の場合は、`：型[]`で表す。

```TS:typescript.ts
let array:number[] = [0, 1, 2];
```

###オブジェクト
オブジェクトは`{key:型}`で表す。

```TS:typescript.ts
interface Name {
  first: string,
  last: string,
};

let fullName: Name = { first: "Yamada", last: "Taro" };
```

`？`をつけると省略可(無くてもOK)となる。

```TS:typescript.ts
interface Name {
  first: string,
  last?: string,
};

let fullName: Name = { first: "Yamada" };
```
###関数
関数の場合、引数の型は明示しなければならない。
引数の( )の後に`:型`指定することで返り値の型を指定できる。

```TS:typescript.ts
const add = (x: number, y: number): number => {
  return x + y
};
```

###type
typeを用いることで型を定義することができる。

```TS:typescript.ts
type Profile = {
  age: number,
  city: string,
};

const user1: Profile = {
  age: 25,
  city: "Tokyo",
};
```

####Intersection Types
typeは`＆`を用いることで拡張することが可能。

```TS:typescript.ts
type Profile = {
  age: number,
  city: string,
};

type Login = {
  userName: string,
  passwoed: string
};

type User = Profile & Login;

const user1: User = {
  age: 25,
  city: "Tokyo",
  userName: "Yamada",
  passwoed: "Taro"
};
```

####Union Types
`|`を用いることで型に`または`という意味を持たせることができる。

```TS:typescript.ts
let value: boolean | number; //boolean型またはnumber型が入る
value = true;
value = 3;

let union: (number | string)[]; //number型またはstring型の要素が入る
union = [1, 2, "Hi"];
```

####Literal Types
stringやnumberのように抽象的な型(プリミティブ型)の指定をする他に、より具体的な型(リテラル型)の指定も行うことができる。
下記の例の場合、companyにはAmazon,Google,Facebookのいずれかの文字列しか代入することはできない。

```TS:typescript.ts
let company: "Amazon" | "Google" | "Facebook";
company = "Amazon"
```

#####型の互換性
抽象的な型(プリミティブ型)に具体的な型(リテラル型)を代入することはできるが、その逆はできない。

```TS:typescript.ts
//string型(comp2)に"test"型(comp1)は代入できる
const comp1 = "test";
let comp2: string = comp1;

//"test"型(comp3)にstring型(comp4)は代入できない
let comp3:string="test";
let comp4:"test"=comp3;
```

####typeof
`typeof`を用いることで他の変数の型を参照することができる。
これはJSONなどの複雑なデータ構造のtypeを参照する時に役立つ。

```TS:typescript.ts
let msg: string = "ya!";
let msg2: typeof msg;
msg2 = "hello"

//オブジェクトの場合
let animal = { genre: "dog" };
let animal2: typeof animal = { genre: "cat" };
```
####keyof
`keyof`を用いるとオブジェクトのkey名を型とすることができる。

```TS:typescript.ts
type keys = {
  primary: string;
  secondary: string;
};

//keyの型は"primary"|"secondary"
let key: keyof keys;
key = "primary"
```

####keyof+typeof
`keyof`と`typeof`は併用可能である。
下記の例の場合、sportsのtypeのkey名をkeySportsの型としている。
(typeof keyof 変数はできないよ。)

```TS:typescript.ts
const sports = {
  soccer: "Soccer",
  baseball: "Baseball"
};

let keySports: keyof typeof sports;
keySports = "soccer"
```

###enum
enumは列挙型と呼ばれ、定数をひとまとめにしておくのに便利な機能である。
指定がなければ、上から順に0,1,2,...と数値が振り分けられる。

```TS:typescript.ts
enum OS {
  Windows, //0
  Mac, //1
  Linux, //2
};
interface PC {
  id: number,
  OSType: OS,
};

const PC1: PC = {
  id: 1,
  OSType: OS.Windows, //0
}
```

###Generics
Genericsは抽象的な型引数を使用して、実際に利用されるまで型が確定しない関数などを実現する為に使用されます。

```TS:typescript.ts
// ケース1　interface
interface Gen<T> {
  item: T;
};
const gen0: Gen<string> = { item: "!!!" }
const gen1: Gen<number> = { item: 12 }

//<>指定しないとエラー
const gen1:Gen={item:12} //エラー

// ケース2
interface Gen1<T = string> {
  item: T;
};
//interfaceで<>の型指定しているので<>不要
const gen3: Gen1 = { item: "hehehe" }

// ケース3
interface Gen2<T extends string | number> {
  item: T;
};
const gen4: Gen2<string> = { item: "hehehe" }

// ケース4 function
function funcGen<T>(props: T) {
  return { item: props }
};
const gen5 = funcGen<string>("TEST")
const gen6 = funcGen<string | null>(null)

// ケース5
function funcGen1<T extends string | null>(props: T) {
  return { value: props }
};
const gen7 = funcGen1("wow")

// ケース6 interface & function
interface Props {
  price: number;
};
function funcGen2<T extends Props>(props: T) {
  return { item: props }
};
const gen8 = funcGen2({ price: 100 })
```

#まとめ
これまでJavascriptで使い慣れていたので、正直Typescriptめんどくさい...っていう印象でした。笑
でも、どんな型で値を渡したり、値が返って来るのかが型推論などですぐに分かるのは便利ですよね。

#参考
・[最速で学ぶTypeScript](https://www.udemy.com/share/103jMO3@Aif_smL1n7OTepF5eV8qs9LPLrBGtILJjPi4vcgCmKTKG3HVw6gPQG8vIv7anQwadg==/)
・[TypeScriptの型入門]
(https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a#%E3%83%AA%E3%83%86%E3%83%A9%E3%83%AB%E5%9E%8B)