Reactは、今やJavaScriptでなく、TypeScriptで書くのが一般的になっています。
ReactでのTypeScriptの使用について、基礎をまとめました!
TypeScriptとは
JavaScriptに型という概念を組み込み、それにより、より安全に、バグが少なく開発できるメリットがある言語です。
そのため基本はJavaScriptと同じで、それに型の定義という概念を追加しただけのもの。
公式ドキュメントはこちら
TypeScriptの使い方
TypeScriptの使用には、アプリ立ち上げの際に以下コマンドを実行します。
$ npx create-react-app プロジェクト名 --template typescript
末尾に–template typescriptを付けるだけ!
基本的な型
基本的な型の、それぞれの定義方法がこちら
// boolean
let bool: boolean = true;
// 数値
let num: number = 0;
// 文字
let str: string = "ABC"
// 配列
// 方法は2通りある
// 1. Arrayを使って型を指定
let arr1: Array<number> = [0, 1, 2];
// 2. 要素の型を指定して[]を付ける
let arr2: number[] = [0, 1, 2];
// どんな型でも入れられるany
let any1: any = false;
// null型
let null1: null = null;
// 何も設定されていないundefined
let undefined1: undefined = undefined
返却値の型指定
関数の引数に型を指定する場合、以下のように記述します。
const calcTotalFee = (num: number): number => {
const total = num * 1.1;
console.log(total);
};
変数の型指定
関数の中の変数に型を指定する場合、以下のように定義する。
const onClickPractice = () => {
let total: number = 0;
total = getTotalFee(1000);
console.log(total);
};
設定tsconfig.json
TypeScriptの設定は、tsconfig.jsonファイルで行います。
create-react-appで立ち上げたときのデフォルトの設定がこちら
{
"include": [
"./src/**/*"
],
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"lib": [
"dom",
"es2015"
],
"jsx": "react-jsx"
}
}
“strict”: true とすることで厳しいルールをまとめて設定しています。
これにより、暗黙的な意味は許可しないといった働きをするため、型定義が必要になる。
デモデータの作成(TypeScriptとは無関係)
データ取得にはaxiosを使うと便利です。
axiosを使うことで、JSONデータの取得を簡単にすることができる。
$ npm install axios --save
JSONplaceholderのtodosを使う。
axiosとjsonplaceholderを使って、ボタンクリックでtodoデータを取得するサンプルコードを作成
.thenで取得後の関数を指定できる。
import axios from "axios";
import "./styles.css";
export default function App() {
const getFetchData = () => {
axios.get("https://jsonplaceholder.typicode.com/todos").then((res) => {
console.log(res);
});
};
return (
<div className="App">
<button onClick={getFetchData}>データ取得</button>
</div>
);
}
useStateの型指定
以下のようにuseStateの後に<>の形で定義を記述します。
const [todos, setTodos] = useState<any>([]);
typeを使った型定義
TypeScriptでは、データ型が無いことによりバグることがある。
そのような型を定義するためには、typeを使ってTodoのアイテムの型定義をします。
type TodoType = {
userId: number;
id: number;
title: string;
complete: boolean;
};
受け取り側の記述
配列の型で取得するので、Arrayで指定し、<>には上記の型定義を指定
const getFetchData = () => {
axios.get<Array<TodoType>>("https://jsonplaceholder.typicode.com/todos").then((res) => {
// console.log(res);
setTodos(res.data);
});
};
setTodosで更新をしているので、useStateも同様に配列の型を定義する必要があります。
const [todos, setTodos] = useState<Array<TodoType>>([]);
propsの型定義
propsの型を、typeをを使って定義する。
type TodoType = {
userId: number;
title: string;
completed: boolean;
}
export const Todo = (props: TodoType) => {
const { title, userId, completed } = props;
const completeMark = completed ? "[完]" : "[未]";
return <p>{`${completeMark} ${title}(ユーザー:${userId})`}</p>;
};
親コンポーネント
{todos.map((todo) => (
<Todo title={todo.title} userId={todo.userId} completed={todo.complete}/>
))}
名前をTodoTypeとし、propsを型定義し、Appから受け取ったpropsを表示している。
型定義の効率化
上記で、Todoコンポーネントの型と、propsの型に同じような型を定義しました。
このような同じような型は共通化してまとめることができます。
src > typesディレクトリを作成し、todo.tsファイルを作成する。
そこにtypeを移換
export type TodoType = {
userId: number;
id: number;
title: string;
complete: boolean;
};
移換元のAppとTodo.tsxでimportを記述
import { TodoType } from "./types/todo"
ただこの2つは全く一緒ではなく、Todo.tsxにはidが不要であるため、要不要を指定できる処理を加える必要があります。
方法は2つ
pickを使用する(必要なプロパティを選択する)方法
抜き出すものを型名とプロパティ名で指定する。
export const Todo = (props: Pick<TodoType, "userId" | "title" | "completed">) => {
上記の場合、userIdとtitle、completedを抜き出している。
omitを使用する(不要なプロパティを選択する)方法
2つ目の方法としては、逆に除くのもを指定することもできる。
export const Todo = (props: Omit<TodoType, "id">) => {
コンポーネント自体の型定義
関数コンポーネントの型を指定するには、FCを使用します。
import { FC } from "react"
type Props = {
color: string;
fontSize: string;
}
export const Text: FC<Props> = (props) => {
引数が無い場合、voidを使って以下のように記述する。
例えば関数colorの引数なし、返却値なしの場合
type Props = {
color: () => void
}
オプショナルチェイニング
?を付け、それ以降のデータを探しに行くかどうかを指定できる。
{user.hobbies?.join(" / ")}
この場合、user.hobbiesの値が無ければ、その時点でundefinedが返される。
オプショナルチェイニングの?を付けていない場合、joinで値の取得ができずエラーとなってしまう。
これを防ぐことができる。
以上、読んでいただきありがとうございました。
コメント