つくる - 丸ごとTS化完了
移行の終点
この回で新しい知識は出てきません。データ層、ユーティリティ、画面まわりと下から上げてきた 3 つを、1 本の関数につなぎます。React入門で書いたポートフォリオの、表示用のまとめ文を作る部分です。
使うのは第4章の interface、第5章の union と分岐、第6章から続く配列メソッドの型です。
つなぐ相手
もとの JavaScript はこうでした。
function buildPortfolioSummary(works, status) {
const titles = works.filter((work) => work.published).map((work) => work.title);
return "公開作品は" + titles.length + "件です。" + titles.join("、");
}動きますが、通信中でも失敗しても同じ文が出ます。作品が 0 件のときは、うしろに何も付かない中途半端な文になります。
形を 2 つ決める
先に型です。作品 1 件の形と、読み込みの状態の 2 つを決めます。
interface Work {
id: number;
title: string;
published: boolean;
}
type LoadStatus = "loading" | "success" | "error";LoadStatus を文字列リテラルの union にしておくと、打ち間違いがその場で止まります。
buildPortfolioSummary(works, "succes");
// エラー Argument of type '"succes"' is not assignable to
// parameter of type 'LoadStatus'.status: string にしていたら、この呼び出しは通ってしまい、画面には何も出ないまま原因が分からなくなります。取りうる値が決まっているものは、string ではなく union にする。これが第5章の結論でした。
状態を先に、中身をあとに
分岐の順番は、外側の状態が先です。
if (status === "loading") {
return "読み込み中です";
}
if (status === "error") {
return "読み込みに失敗しました";
}ここを抜けた時点で、status は "success" に絞り込まれています。TypeScript も同じように絞っているので、この先で status にホバーすると "success" とだけ出ます。
残りは中身の話です。公開作品が 1 件も無いときは、件数を並べても意味がないので別の文にします。
手を動かす
引数に型を通し、状態の分岐と 0 件の分岐を足してください。順番はいつもどおり、型を付けてから中身です。
この関数が通ったら、React入門のコードのうち関数とデータ層は、丸ごと TypeScript に載りました。ここで作った Work と LoadStatus は、そのまま次のコースへ持っていきます。
要件
- 作品 1 件の形を
Workという名前で定義する - 読み込み状態を
loadingとsuccessとerrorだけを取る型として定義する - 引数と戻り値に型を付ける
loadingのときは読み込み中ですを返すerrorのときは読み込みに失敗しましたを返すsuccessで公開作品が 0 件のときは公開作品はまだありませんを返す
入出力例
buildPortfolioSummary([{"id":1,"published":true,"title":"プロフィールサイト"},{"id":2,"published":false,"title":"自己紹介カード"},{"id":3,"published":true,"title":"スキル一覧の表"}], "success") → "公開作品は2件です。プロフィールサイト、スキル一覧の表"
buildPortfolioSummary([], "loading") → "読み込み中です"
buildPortfolioSummary([{"id":1,"published":true,"title":"プロフィールサイト"}], "error") → "読み込みに失敗しました"
buildPortfolioSummary([{"id":9,"published":false,"title":"下書きメモ"}], "success") → "公開作品はまだありません"
buildPortfolioSummary([], "success") → "公開作品はまだありません"
buildPortfolioSummary([{"id":1,"published":true,"title":"プロフィールサイト"},{"id":2,"published":true,"title":"自己紹介カード"}], "success") → "公開作品は2件です。プロフィールサイト、自己紹介カード"