Part 0 · React の前に
TypeScript のさわり
型があると、なぜ書くのが楽になるのか
TypeScript は、JavaScript に「この値はこういう形をしている」という説明を書き足せるようにしたものです。別の言語ではありません。
型は書く手間が増えるだけに見えますが、実際は逆です。書く量より、間違いを探す時間のほうがずっと減ります。
この章では、React を読むために最低限必要なところだけをやります。 全部を覚える必要はありません。
型があると何が変わるか
型がないと、間違いは動かしてみるまで分かりません。
// JavaScript
const user = { name: "さとう" };
console.log(user.nmae); // undefined(打ち間違いに気づけない)nmae と打ち間違えても、JavaScript は何も言わずに undefined を返します。 画面に何も出ない理由を探して何十分も溶かす、というのがよくある流れです。
型を書いておくと、書いているその場で赤線が引かれます。
// TypeScript
type User = { name: string };
const user: User = { name: "さとう" };
user.nmae; // エラー: User に nmae はありませんmember-type.ts
// データの形に名前をつける
type Member = {
id: number;
name: string;
// ? を付けると「なくてもいい」項目になる
nickname?: string;
};
const members: Member[] = [
{ id: 1, name: "さとう", nickname: "さっちゃん" },
{ id: 2, name: "すずき" },
{ id: 3, name: "たかはし", nickname: "たか" },
];
// nickname は undefined のことがあるので ?? で補う
export const labels = members.map((member) => member.nickname ?? member.name);書き方は「値のうしろに : 型」
const name: string = "さとう";
const age: number = 20;
const isAdmin: boolean = false;
// 配列は「何の配列か」を書く
const names: string[] = ["さとう", "すずき"];
// オブジェクトは形をそのまま書く
const user: { name: string; age: number } = { name: "さとう", age: 20 };ただし、ほとんどの場合型を書く必要はありません。 代入した値から自動で判断してくれるからです。
const name = "さとう"; // string だと分かってくれる型を明示するのは、主に関数の引数とデータの形を決めるときです。 React では、これが props の型になります。
type で形に名前をつける
同じ形を何度も書くのは大変なので、名前をつけて使い回します。
type Member = {
id: number;
name: string;
nickname?: string; // ? は「なくてもいい」
};? を付けた項目は、あってもなくても構いません。 その代わり、使うときは「ないかもしれない」前提で扱う必要があります。
nickname がない人は name で表示される
あだ名があればそちら、なければ名前
- さっちゃん
- すずき
- たか
member.nickname ?? member.name の ?? は前の章でやったものです。 TypeScript は「nickname は undefined かもしれない」と知っているので、 この対処を書かずに使おうとすると警告してくれます。型が、書き忘れを防いでくれているわけです。
member-type.ts
// データの形に名前をつける
type Member = {
id: number;
name: string;
// ? を付けると「なくてもいい」項目になる
nickname?: string;
};
const members: Member[] = [
{ id: 1, name: "さとう", nickname: "さっちゃん" },
{ id: 2, name: "すずき" },
{ id: 3, name: "たかはし", nickname: "たか" },
];
// nickname は undefined のことがあるので ?? で補う
export const labels = members.map((member) => member.nickname ?? member.name);取りうる値を決めてしまう
TypeScript でいちばん便利なのが、「この値はこの 3 つのどれか」と決められることです。
type Status = "todo" | "doing" | "done";
const status: Status = "doing"; // OK
const wrong: Status = "yet"; // エラー縦棒(|)で区切って並べるだけです。これを union と呼びます。 文字列を直接書けるので、ステータスや種類を表すのにぴったりです。
status に想定外の値が入る余地がない
- 資料をまとめる完了
- レビューを依頼する作業中
- 公開する未着手
Record<Status, string> は 「Status のすべてに対して文字列を用意する」という意味です。 あとから Status に種類を足すと、用意し忘れた場所がエラーで教えてもらえます。 これが型のありがたみを最も感じる瞬間です。
union-type.ts
// 取りうる値そのものを列挙して、型にできる
export type Status = "todo" | "doing" | "done";
// Status のすべてに対して、ひとつずつ用意することを強制される。
// 増やし忘れがあるとエラーになる
const statusLabel: Record<Status, string> = {
todo: "未着手",
doing: "作業中",
done: "完了",
};
const tasks: { title: string; status: Status }[] = [
{ title: "資料をまとめる", status: "done" },
{ title: "レビューを依頼する", status: "doing" },
{ title: "公開する", status: "todo" },
];
export const rows = tasks.map((task) => ({
title: task.title,
label: statusLabel[task.status],
}));React ではこう使う
型を書く場所は、React ではほぼ 1 か所です。コンポーネントが受け取る値(props)のところ。
type Props = {
name: string;
age?: number;
};
function Profile({ name, age }: Props) {
return <p>{name}({age ?? "非公開"})</p>;
}ここには、Part 0 でやったことがすべて出てきています。
{ name, age }… 分割代入: Props… 型注釈age?… あってもなくてもいい項目??… ないときの代わりの値
この形が読めるようになれば、React のコンポーネントは ほぼすべて読めます。Part 2 でここを本格的に扱います。
member-type.ts
// データの形に名前をつける
type Member = {
id: number;
name: string;
// ? を付けると「なくてもいい」項目になる
nickname?: string;
};
const members: Member[] = [
{ id: 1, name: "さとう", nickname: "さっちゃん" },
{ id: 2, name: "すずき" },
{ id: 3, name: "たかはし", nickname: "たか" },
];
// nickname は undefined のことがあるので ?? で補う
export const labels = members.map((member) => member.nickname ?? member.name);理解できたか確かめる
確認クイズ
type Member = { name: string; nickname?: string } の ? は何を意味する?
確認クイズ
type Status = 'todo' | 'doing' | 'done' の利点は?
member-type.ts
// データの形に名前をつける
type Member = {
id: number;
name: string;
// ? を付けると「なくてもいい」項目になる
nickname?: string;
};
const members: Member[] = [
{ id: 1, name: "さとう", nickname: "さっちゃん" },
{ id: 2, name: "すずき" },
{ id: 3, name: "たかはし", nickname: "たか" },
];
// nickname は undefined のことがあるので ?? で補う
export const labels = members.map((member) => member.nickname ?? member.name);この章のまとめ
- TypeScript は JavaScript に「値の形の説明」を足したもの
- 型の利点は、間違いを実行する前に見つけられること
- ほとんどは自動で判断されるので、書くのは関数の引数とデータの形くらい
?は任意の項目、|は「このどれか」- React では props の型として使う。Part 2 で本格的に扱う
member-type.ts
// データの形に名前をつける
type Member = {
id: number;
name: string;
// ? を付けると「なくてもいい」項目になる
nickname?: string;
};
const members: Member[] = [
{ id: 1, name: "さとう", nickname: "さっちゃん" },
{ id: 2, name: "すずき" },
{ id: 3, name: "たかはし", nickname: "たか" },
];
// nickname は undefined のことがあるので ?? で補う
export const labels = members.map((member) => member.nickname ?? member.name);