Reactに向けたTypeScript

# TypeScript(TS)とは
***JavaScript(JS)を拡張したプログラミング言語***です。
Reactでよく使われます。Vue.js,Angular.jsなどでも使われます。

# 有益教材
こちらのUdemyはReactですが、有益な内容です。
TypeScriptも入っているのでおすすめです。

https://www.udemy.com/course/react-complete-guide/

TypeScriptに限らず、Reactの学習法など詳しく解説されています。

https://read-engineer.com/2020/12/21/typescript/

# TSの特徴
1.***JavaScriptに変換してから実行***
これは
```
% tsc ファイル名
```
の***コマンドで変換***します。

2.***型の定義ができる***

3.***JSにない記述ができる***

# TSのメリット
型が定義されるので他のメンバーがわかりやすい
バグを前もって検知できる
VSCodeで自動補完できる

などあります。

# TSの導入
***TypeScriptの導入***です。
``` 
npm install -g typescript 
```
Reactを使った導入です。
``` 
npx create-react-app {プロジェクト名} --template typescript
```
今回はReactも使う環境で書いていきます。
ここで以下のファイル名でtscコマンドを実行します。
```
% tsc hello.ts
```

# プリミティブな値の型の定義
まずは
1.***string型***
```Practice.tsx
const Practice = () => {
  let str: string = 'こんにちは';
  str = "やあ";
  console.log(str);
};

export default Practice;
```
2.***number***

```Practice.tsx
const Practice = () => {
  let num: number = 1000;
  console.log(num);
};

export default Practice;
//1000
```
***numberも省略***できます。
```Practice.tsx
const Practice = () => {
  let num = 1000;
  console.log(num);
};

export default Practice;
//1000
```

***numberで処理できないくらい大きい数***の場合は```bigint```を使います。

3.***boolean***

```Practice.tsx
const Practice = () => {
  let bool: boolean = true;
  console.log(bool);
};

export default Practice;
//true
```

4.***nullとundefined***
```Practice.tsx
const Practice = () => {
  let nullish: null = null;
  let undefinedValue: undefined = undefined;
};

export default Practice;
```

5.***リテラル型***
***特定の値を型としてもてます***。

```Practice.tsx
const Practice = () => {
  let trueVal: true = true;
  let num100: 100 = 100;
  let strHello: 'Hi' = 'Hi';
};

export default Practice;
```

# ユニオン型
ユニオン型(union type)は、***複数の型を組み合わせ***て```「または」の意味```を表すことができます。

```Practice.tsx
  const Practice = () => {
  type HiOrNumber = 'Hi' | number;
  const hello: HiOrNumber = 'Hi';

  type DayOfWeek =
    | 'Saturday'
    | 'Sunday'

  const day: DayOfWeek = 'Monday';
}
```

# 配列とオブジェクトの型定義
まずは配列の定義方法からです。

```practice.jsx
 const Practice = () => {

    const score: number[] = [80,60,70];
    const greet: string[] = ['こんにちは','ニーハオ','ハロー'];
    const arry: Array<number> = [10,20,30];
    const player: (string | number)[] = ['大谷',17];
    const player2:  Array<string | number> = ['メッシ',30];
};

export default Practice;
```
次は***オブジェクトの型の定義***からです。
```practice.jsx
 const Practice = () => {


type Player = {name: string,age?:number}
    const object1: Player = { name: 'Messi' };

    const users: Player[] = [
      {name: 'Messi'},
      {name: '大谷',age:28} 
    ]
};
export default Practice;
```

# 型推論(type inference)
***型をある程度推測してくれる機能***です。
基本はこの型定義はこの機能に任せていいくらいです。

```Paractice.jsx
const Practice = () => {
    let str = 'オラ！';
    let obj = { name: 'Messi', age: 35 };

};

export default Practice;
//

```
objのあたりにカーソルをもっていくと以下のように出てきます。
```
//let obj: {
   // name: string;
    age: number;
}
```

# 型エイリアス
TSでは```Type文を使って型に別名をつけることができ```る***type alias(型エイリアス)***があります。

```Practice.jsx
const Practice = () => {
  type Player = {
    name:string;
    age:number;
  }
  const player: Player = {name: '大谷',age:28}

  type PlayerName = string;
  type PlayerAge = number;
  type PlayerPosition = "pitcher" | "catcher" | "infielder" | "outfielder";
  
  type PlayerProfile = {
    name:PlayerName,
    age:PlayerAge,
    position:PlayerPosition,
  }

  const playerProfile: PlayerProfile = {
    name:'大谷',
    age:28,
    position:'pitcher'
  }
};

export default Practice;
```

# 関数の定義
関数の定義方法です。まずは```引数```からです。
```Practice.jsx
const Practice = () => {
  //練習用
  function sum1(A:number,B:number){
    return A + B;
  }

  const sum2 = (A: number,B: number) => A + B;
};

export default Practice;
```
次は```戻り値```です。
```Practice.jsx
const Practice = () => {
  //練習用
  function sum1(A:number,B:number): void{
    // return A + B;
  }

  const result1 = sum1(10,20);

  const sum2 = (A: number,B: number):string=> "こんにちは";
  const result2 = sum2(100,200);

  type Sum = (x:number,y:number) => number;
  const sum3: Sum = (x,y)=> x + y;
  const result3 = sum3(1,2);
};

export default Practice;
```


# ジェネリクス関数
```型引数(type paramaters)```を***受け取る関数を作る機能***のことを指します。

```Practice.tsx
const Practice = () => {
  // 練習用
  const repeatStr = (value: string,times:number): string[] => {
    return new Array(times).fill(value);
  }
  const repeatNum = (value: number,times:number):number[] => {
    return new Array(times).fill(value);
  }
  
  // const strArry = repeatStr("こんにちは",5);
  // const numArry = repeatNum(1,5);
  // console.log(strArry);
  // console.log(numArry);
};

export default Practice;
```

追加で以下にコードを書いていきます。
下のように<T>などでで定義をします。

```Practice.tsx
const Practice = () => {
  const repeat = <T>(value: T, times:number): T[] =>{
    return new Array(times).fill(value);
  }
  const numArry = repeat<number>(10,3);
};

export default Practice;
```
Tがnumberなどで実行されます。

```Practice.tsx
const Practice = () => {
   const repeatStr = (value: string,times:number): string[] => {
     return new Array(times).fill(value);
  }
  const repeatNum = (value: number,times:number):number[] => {
     return new Array(times).fill(value);
   }
  const repeat = <T>(value: T, times:number): T[] =>{
    return new Array(times).fill(value);
  }
  const numArry = repeat<number>(10,3);
  const strArry = repeat<string>("こんにちは",5);
  const boolArry = repeat<boolean>(true,3);
  const helloArry = repeat<"hello">("hello",3);
  
   console.log(strArry);
  console.log(numArry);
  console.log(boolArry);
  console.log(helloArry);
};

export default Practice;
```


# 関数コンポーネントに型を入れる
関数のコンポーネントの定義のやり方です。うまく行かない場合はサーバーを起動し直してください。

```Practice.tsx
import Hello from "./Greeting";

const Example: React.FC = () => {
    // 練習
return < Greeting/>
};

export default Practice;
```

```Greeting.tsx
const Greeting: React.FC = () => {
    return <h1>ReactでTypeScript学習</h1>
}

export default Greeting;
//ReactでTypeScript学習
```

# propsに型を定義
propsの型の定義の仕方を見ていきます。


```Greeting.tsx
type HelloProps = {
    text:string,
    children: React.ReactNode
}

const Greeeting: React.FC<HelloProps> = (props) => {
    return <h1>こんにちは{props.text}の{props.children}</h1>;
}
export default Greeting;
```

```Practice.tsx
import Greeting from "./Greeting";

const Greeting: React.FC = () => {
  return <Hello text="TypeScript">children!</Hello>;
};

export default Practice;
//こんにちはTypeScriptのchildren!
```
ボタンを出力させます。

```Greeting.tsx
type GreetingProps = {
    text: string;
    children: React.ReactNode;
  }
  
  const Greeting: React.FC<GreetingProps> = (props) => {
    return <h1>こんにちは{props.text}の{props.children}</h1>;
  }
  
  type FnProps = {
    fn: (text: string) => void;
  }
  
  export const Button: React.FC<FnProps> = (props) => {
    return <button onClick={() => props.fn('TypeScript')}>ボタン</button>;
  }
  
  export default Greeting;
```

```Practice.tsx
import Greeting from "./Greeting";
import { Button } from "./Greeting";

const Practice: React.FC = () => {

  return (
    <>
      <Button fn={(text) => console.log(`Hello ${text}`)} />
      <Hello text="TypeScript">children!</Hello>
    </>
  );
};

export default Practice;
//ボタンが出現
//こんにちはTypeScriptのchildren!
```

# useStateを型で定義
useStateで型の定義をやっていきます。

```Practice.tsx
import { useState } from "react";

type Tobe = {
    id:number,
    text:string
}

type Player = {
    name:string,
    age:number;
}

const Example = () => {
    const [text,setText] = useState("やあ");
    const [sports,setSports] = useState<string[]>(["Baseball","Soccer"]);
    const [players,setPlayers] = useState<Player[]>([{name:'大谷',age:28}]);

    const [tobe,setTobe] = useState<Tobe[]>([{id:0,text:"ポジティブ"}])
};

export default Practice;
```

# Todo機能
最後にTodoの機能を作っていきます。

```TaskList.tsx
import { Todo } from "./Practice";

type TaskListProps = {
  todos: Todo[];
};

const TaskList: React.FC<TaskListProps> = (props) => {
  return (
    <ul>
      {props.todos.map((todo) => {
        return <li key={todo.id}>{todo.text}</li>;
      })}
    </ul>
  );
};
```

```Practice.tsx
import { useState } from "react";
import TaskList  from "./TaskList";

export type Todo = {
    id: number,
    text: string
}

const Practice = () => {
  const [inputText,setInputText] = useState("");
  const [todos,setTodos] = useState<Todo[]>([
    {id:0,text:'Todo1'},
    {id:1,text:'Todo2'},   
  ]);
  const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => 
  setInputText(e.target.value);

  const addTodoItem = ()=>{
  setTodos(state => [...state,{id: state.length,text:inputText}]);
  setInputText("");
  }
return (
  <>
  <input type ="text" value={inputText} onChange={changeHandler} />
  <button onClick={addTodoItem}>追加</button>
  <TaskList todos={todos}/>
  </>
)

};
export default Practice;
```


# 資料

https://www.udemy.com/course/react-complete-guide/