search
LoginSignup
60

posted at

updated at

Organization

6歳娘「パパ、any型よりunknown型がいいんじゃない?」

リモートワーク中ワイ

ワイ「あー、いそがし、いそがし・・・と」
ワイ「よし、Slackでこう呟いておけば、仕事してる感が出るやろ」

娘「ねぇ、パパ」
娘「質問していい?」

ワイ「ええで、娘ちゃん」

娘「今、とある会社さんのコーポレートサイトを作ってるの」

ワイ「おお、そうなんか」
ワイ「娘ちゃんも、もう小学1年生やもんな」
ワイ「そんな事もできるようになったんやな」

娘「うん」
娘「それで、TypeScriptについて分からないことがあるの」

ワイ「なんや?パパが教えてあげるで」

娘「ありがとう、パパ!」

何について困っているのか

娘「実は、クライアントさんから」
娘「こんな要望が来ているの」

クライアント「以下のような関数を作ってほしいです」
 

  • 引数として、どんな型の値でも受け取れる
  • 引数がもし配列だったらpop()メソッドで末尾の要素を取り出し、戻り値として返す
  • 引数が配列でなかったら、undefinedを返す

ワイ「ふーん」
ワイ「・・・何のために?」
ワイ「一体どんな会社さんなん?」

娘「配列だったらポップしてちょうだい株式会社さんっていうんだけど」

ワイ「配列だったらポップしてちょうだい株式会社さん!?」
ワイ「まるで、この記事のために考えられたかのような会社名やな」

娘「とにかく、どんな型の値でも受け取れる
娘「そんな関数を作りたいの」

ワイ「なるほど、パパに任せてや!」

あの型を使ってしまえ

ワイ「じゃあ、まず関数の名前を考えるで」
ワイ「配列かもしれない値から、末尾の要素をpop()するから」
ワイ「関数名はpopFromMaybeArrayや!」

    const popFromMaybeArray = () => {
      /* ここに処理を書く */
    }

ワイ「↑こうやな」
ワイ「ほんで、引数としてはどんな型でも受け取りたいわけやな」
ワイ「そして、返り値の型も不明やから・・・」

    const popFromMaybeArray = (maybeArray: any): any => {
      /* ここに処理を書く */
    }

ワイ「↑こうや!」
ワイ「any型を使ってやるわけや!」
ワイ「これで完璧や!」

娘「パパ、ありがとう!」
娘「ワーイ!」

ワイ「ワーイ!」

ミスに気づけなさ過ぎて、つらい

娘「パパ、これじゃあやりづらいよ」

ワイ「そうなん・・・?」

娘「だって・・・」

    const popFromMaybeArray = (maybeArray: any): any => {
      maybeArray.poppu() // コンパイルエラーなし
      maybeArray.hoge() // コンパイルエラーなし
    }

娘「↑ほら」
娘「any型だと、どんなにメソッド名を間違えたりしても
娘「コンパイルエラーが出ないから」
娘「ミスに気づけないよ・・・」
娘「せっかくTypeScriptを使っているのに・・・」

ワイ「ほんまやな・・・」

娘「これじゃ、絶対に実行時エラーが出ちゃうよ」
娘「型安全性が皆無だよ」

ワイ「Oh・・・」
ワイ「ほな、どうしよう・・・」

娘「あっ」
娘「パパ、もしかして」
娘「unknown型を使えばいいんじゃない?」

ワイ「なんやて?unkoウンコ...?」

娘「unknownアンノウンよ」

ワイ「ああ、そっちか」

unknown型を使ってみる

娘「えっと、any型だったところを」
娘「unknown型にするから・・・」

    const popFromMaybeArray = (maybeArray: unknown): unknown => {
      /* 省略 */
    }

娘「↑こうだね!」
娘「ほら、コンパイルエラーが表示されたよ!」

スクリーンショット 2022-05-21 10.29.25.png

ワイ「へー」
ワイ「unknown型は、何でも受け取れるけど」
ワイ「anyみたいに何でも許してしまう訳ではなくて」
ワイ「ちゃんとコンパイルエラーを出してくれるんやな」
ワイ「any型安全版って感じ?」

娘「そうだね」

ワイ「なるほどな」
ワイ「unknown、つまり不明な値やから」
ワイ「poppu()メソッドやhoge()メソッドを持ってるかは分からへんから」
ワイ「実行できません、ってことをエラーで教えてくれてる感じやな?」
ワイ「ほな、どうすればええんやろ?」

娘「えっとね」
娘「引数が配列じゃなかった場合には先に進めないように、型ガードしてやればいいんだよ」

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

娘「見ててね」

    const popFromMaybeArray = (maybeArray: unknown): unknown => {
+     // 引数が配列じゃない場合には、早期return。
+     if (!Array.isArray(maybeArray)) return undefined
      maybeArray.poppu()
      maybeArray.hoge()
    }

娘「↑こうだね!」

ワイ「なるほど」
ワイ「配列かどうか、Array.isArray()でチェックして」
ワイ「配列じゃない場合には、早期リターンしてやるんやな」

娘「そうだよ」
娘「こうしてあげると・・・」

スクリーンショット 2022-05-21 10.42.20.png

娘「ほら、メソッド名の間違いを指摘してくれたよ」

ワイ「なるほどな」
ワイ「maybeArray配列であることが確定したから」

TSコンパイラ「配列はpoppuなんて持ってないですよ」

ワイ「って指摘してくれたわけやな」
ワイ「型安全な感じになってきたな」

娘「うん」
娘「あとは、末尾の要素をpop()して」
娘「返してあげればいいから・・・」

    const popFromMaybeArray = (maybeArray: unknown): unknown => {
      // 引数が配列じゃない場合には、早期return。
      if (!Array.isArray(maybeArray)) return undefined
+     // 末尾の要素を取得。
+     const lastItem: unknown = maybeArray.pop()
+     return lastItem
    }

娘「↑こうだね!」

動作確認してみる

// 配列を渡してみる
const a = popFromMaybeArray([1, 2, 3])
console.log(a) // -> 3

// 文字列を渡してみる
const b = popFromMaybeArray("文字列")
console.log(b) // -> undefined

娘「うん」
娘「配列を渡した場合には、末尾の要素が返ってくるし」
娘「そうじゃない場合には、undefinedが返ってきてる」

ワイ「おお、ほんまや!」
ワイ「これで、配列だったらポップしてちょうだい株式会社さんも大喜びやな!」

娘「うん!」
娘「さっそく配ポップさんに連絡してみる!」

ワイ「配ポップさんって呼んでるんや」

まとめ

  • unknown型とは
    • どんな型の値でも代入できる
    • でもany型と違って型安全
    • unknown型のままでは何もできない
      • if文などで型を絞り込んでやることで色々できる
    • どんな値が来るのか不明な場合に使える

その日の夜

ワイ「なるほどなぁ」
ワイ「どんな型でも受け取りたい場合はanyを使うしかないのかと思ってたわ」
ワイ「型安全なunknownなんていう型もあったんやなぁ」

娘「そうだね」
娘「ところでパパ、今日お仕事だったんでしょ?」
娘「私と話してばっかりで、殆どお仕事してなかったんじゃない?」
娘「今日、コードは何行書いたの?」

ワイ「実は・・・まだ0行や・・・グビッ(ビールを飲む音)」
ワイ「アレや」
ワイ「最近話題の・・・ノーコードいうやつやな」

娘「ノーコード・・・聞いたことある!」
娘「パパ、ノーコードで稼いでるんだ!」
娘「すご〜い!」

ワイ「ワーイ!」

よめ太郎「それ給料泥棒やないかい」

〜おしまい〜

注意

  • 引数で受け取った配列に対してpop()等の破壊的操作を行うとバグの温床になるので、普通はやめましょう。
  • 配ポップ社さんの案件のときだけにしましょう。

新しい記事もよろしくやで

Zennにも記事を書いてみましたやで

noteも書いてますやで

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
What you can do with signing up
60