416
158

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

吾輩はバグを出す 〜Mapped typesでミス対策〜

Last updated at Posted at 2020-09-15

ある日、某システム会社にて

ワイ「カタカタカタカタ・・・」

ハスケル子「やめ太郎さん」
ハスケル子「さっきから一生懸命、何を書いてるんですか?」

ワイ「小説や」
ワイ「これで一発当てて、会社なんて辞めてやるんや・・・!」

ハスケル子「へえ〜、それは凄いですね(棒読み)」
ハスケル子「ちょっと読ませてくださいよ」

ワイ「ええで」

ハスケル子「ええと、タイトルは」
ハスケル子「・・・吾輩はバグを出す・・・?」
ハスケル子「なるほど」
ハスケル子「ノンフィクション小説ですね?」

ワイ「どういう意味やねん
ワイ「フィクションや、フィクション」

仕事をしろ

ハスケル子「それよりやめ太郎さん」
ハスケル子「今日から新しい仕事が始まりますよ」
ハスケル子「株式会社ジャンケンポンさんの、コーポレートサイトを作るお仕事です」

ワイ「ああ、せやったな」
ワイ「どんなサイトを作るんやったっけ」
ワイ「仕様書を読んでみよか」

  • トップページで「ジャンケンゲーム」ができるようにして欲しい。

ワイ「なるほどな」
ワイ「社名にちなんで、って事やな」

ハスケル子「じゃあ、早速ペアプロしていきましょうか」

ワイ「せやな」

ペアプロ開始

ワイ「ジャンケンと言えば、グー・チョキ・パーやな」
ワイ「ワイはよく、チョキをチャカって打ち間違えてしまうから」
ワイ「それを防ぐために、ちゃんと型をつけておかんとな」

ハスケル子「そうですね」
ハスケル子「チャカを出したらまずいですもんね」

ワイ「そういうことや」
ワイ「せやから・・・」

type Hands = "グー" | "チョキ" | "パー";

ワイ「↑これでええな」
ワイ「これで、Hands型の変数には"グー""チョキ""パー"しか代入できひん」

type Hands = "グー" | "チョキ" | "パー";

const hand: Hands = "チャカ"; // コンパイルエラー!

ワイ「↑こんな感じで」
ワイ「チャカの混入を防げるってわけや」
ワイ「テキストエディタ上でも・・・」

スクリーンショット 2020-09-15 22.29.29.png

ワイ「↑こんな感じで、ちゃんと赤い波線が表示されて」
ワイ「ミスに気付けるで」

ハスケル子「いいですね」

ワイ「やっぱ静的型付け言語ってええなぁ」
ワイ「ブラウザ上で実際にコードを動かす前に」
ワイ「テキストエディタでコードを書いてる段階でエラーに気づけるから、便利やな」

ハスケル子「そうですね」
ハスケル子「矛盾が生じるようなコードを書いてしまった時に」
ハスケル子「事前に気づけるから効率的ですよね」

ワイ「そうそう」

ハスケル子「間違えないように人間が気をつけてプログラミングをするより」
ハスケル子「間違えたらコンパイラが怒ってくれる方が良いですもんね」

ワイ「せやせや」

ところが

ハスケル子「でもやめ太郎さん」
ハスケル子「このサイト、日本語だけじゃなくて」
ハスケル子「英語での表示もしないといけないみたいですよ」

ワイ「マジかいな」
ワイ「どれどれ、仕様書には何てかいてあんねん」

  • 英語での表示もできること。
  • 英語モードのときは「グー・チョキ・パー」を「Rock・Scissors・Paper」と表示すること。

ワイ「Oh...」
ワイ「どうすればええねん・・・」

閃いた

ワイ「分かったで」
ワイ「こういうオブジェクトを作ればええんや」

// 日本語用
const handsJa = {
    gu: "グー",
    choki: "チョキ",
    pa: "パー",
};

// 英語用
const handsEn = {
    gu: "Rock",
    chaka: "Scissors",
    pa: "Paper",
};

ワイ「↑こうしておけば・・・」

console.log(handsJa["gu"]); // グー

console.log(handsEn["gu"]); // Rock

ワイ「↑こんな感じで、"gu"という文字列を」
ワイ「日本語の"グー"に変換して表示したり」
ワイ「英語の"Rock"に変換して表示したりできるわけや」

ハスケル子「なるほど」
ハスケル子「対応表っぽいオブジェクトを作るわけですね」

ワイ「せや」
ワイ「基本的には"gu""choki""pa"という文字列を使って処理を行って」
ワイ「画面に表示するときだけは対応表オブジェクトを通して日本語や英語に変換する感じや」
ワイ「そうすれば、アルゴリズムの部分は日本語と英語を分けずに、共通化できるで!」

ハスケル子「良さげですね」
ハスケル子「でもやめ太郎さん」

    chaka: "Scissors",

ハスケル子「↑さっそくチャカが混入してますよ」

ワイ「ファッ!?
ワイ「chokichakaって打ってもうたんか」

ワイ「またチャカを打ってもうたぁ〜!!!」

ハスケル子「やめ太郎さん、語弊がエグいです
ハスケル子「通報されますよ」

プロパティ名をタイポしないために

ワイ「ワイはすぐタイポしてしまうなぁ」
ワイ「これじゃTypeScriptやなくてタイポスクリプトやで」
ワイ「・・・言うてる場合ちゃうわ」
ワイ「ほんま、気をつけんとなぁ・・・」

ハスケル子「やめ太郎さん」
ハスケル子「いつもそう言って」
ハスケル子「気をつけられた試しがないじゃないですか」

ワイ「ぐぬぬ」

ハスケル子「ここはTypeScriptの力を頼りましょう

ワイ「と言いますと・・・」

ハスケル子「Mapped typesを使いましょう」

Mapped typesを使ってみる

ハスケル子「まずは・・・」

type Hands = "gu" | "choki" | "pa";

ハスケル子「↑こうです」

ワイ「Hands型の変数には、"gu""choki""pa"しか代入できませんよ、ていう」
ワイ「そういう感じやな」

ハスケル子「はい」
ハスケル子「ここでMapped typesを使います」

type HandsDisplay = {
    [P in Hands]: string
};

ハスケル子「↑こうです」

ワイ「え?」
ワイ「ワイはてっきり・・・」

type HandsDisplay = {
    gu: string
    chaka: string
    pa: string
};

ワイ「↑こうかと思ってたわ」

ハスケル子「同じことですね」

ワイ「そうなんや」
ワイ「Hands型の値と対応したプロパティ名・・・」
ワイ「つまり"gu""choki""pa"というプロパティ名を持つ」
ワイ「そんなオブジェクト型を、サクッと書けるわけか」
ワイ「短く書けて便利やね」

ハスケル子「短いのも良いんですけど、それよりも」
ハスケル子「Hands型を元に、オブジェクトの型を自動っぽく生成できるのがメリットですね」

ワイ「ふーん」
ワイ「そこ自動化するくらいでメリットある?」

ハスケル子「あります」
ハスケル子「その証拠に、やめ太郎さんが手動で書いたHandsDisplay型には・・・」

    chaka: string

ハスケル子「↑チャカが混入しています」

ワイ「ぐぬぬ」

type HandsDisplay = {
    [P in Hands]: string
};

ハスケル子「↑こうやって」
ハスケル子「Mapped typesを使って書けば」
ハスケル子「guchokipaというプロパティを持つオブジェクト型を」
ハスケル子「確実に生成できます」
ハスケル子「仮に、Hands型の値が数百種類だったとしてもミスりません」
ハスケル子「chakaも混入しません」

スクリーンショット 2020-09-15 22.28.30.png

ハスケル子「ほら」
ハスケル子「ちゃんとchakaの部分にエラーが出てます」

ワイ「なるほどな」
ワイ「ある型に対応した、オブジェクト型を定義する・・・」
ワイ「Mapped typesを使うとそんなことができるんやな」

ハスケル子「そうですね」
ハスケル子「mapという単語には」
ハスケル子「対応づけるとか対応表って意味もありますからね」

ワイ「おお、対応表か」
ワイ「何かに対応したプロパティ名を持つオブジェクト型、って」
ワイ「割と作りたいときあるから」
ワイ「そんなときにはMapped typesを使わしてもらうわ!」
ワイ「値の種類が多い場合なんか、特に便利やな!」

ハスケル子「Hands型の値の種類が数百に増えた場合にも」
ハスケル子「HandsDisplay型は自動で追従してくれますしね!」

ワイ「おお、良さげやな!」

社長「(ジャンケンの手、そんな増えへんやろ・・・)」
社長「(片手でどうやって表現すんねん・・・)」

まとめ

ワイ「吾輩はバグを出す」
ワイ「知能はまだない」
ワイ「どこでバグらせたか、とんと見当がつかぬ」
ワイ「だから、TypeScriptを導入して」
ワイ「コンパイラに見つけてもらおう」

ハスケル子「そういうことですね」

〜おしまい〜

416
158
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
416
158

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?