リモートワーク中ワイ
ワイ「あー、いそがし、いそがし・・・と」
ワイ「よし、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 => {
/* 省略 */
}
娘「↑こうだね!」
娘「ほら、コンパイルエラーが表示されたよ!」
ワイ「へー」
ワイ「unknown
型は、何でも受け取れるけど」
ワイ「any
みたいに何でも許してしまう訳ではなくて」
ワイ「ちゃんとコンパイルエラーを出してくれるんやな」
ワイ「any
の型安全版って感じ?」
娘「そうだね」
ワイ「なるほどな」
ワイ「unknown
、つまり不明な値やから」
ワイ「poppu()
メソッドやhoge()
メソッドを持ってるかは分からへんから」
ワイ「実行できません、ってことをエラーで教えてくれてる感じやな?」
ワイ「ほな、どうすればええんやろ?」
娘「えっとね」
娘「引数が配列じゃなかった場合には先に進めないように、型ガードしてやればいいんだよ」
ワイ「と言いますと・・・?」
娘「見ててね」
const popFromMaybeArray = (maybeArray: unknown): unknown => {
+ // 引数が配列じゃない場合には、早期return。
+ if (!Array.isArray(maybeArray)) return undefined
maybeArray.poppu()
maybeArray.hoge()
}
娘「↑こうだね!」
ワイ「なるほど」
ワイ「配列かどうか、Array.isArray()
でチェックして」
ワイ「配列じゃない場合には、早期リターンしてやるんやな」
娘「そうだよ」
娘「こうしてあげると・・・」
娘「ほら、メソッド名の間違いを指摘してくれたよ」
ワイ「なるほどな」
ワイ「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()
等の破壊的操作を行うとバグの温床になるので、普通はやめましょう。 - 配ポップ社さんの案件のときだけにしましょう。