5妥協しないTypescriptJavaScriptTypeScriptReactテックタッチアドベントカレンダー5日目を担当する@takakobemです。4Kモニタいいですよね。以前私は43型の4Kモニタを使っていたのですが、正直でかすぎて画面の端が見づらかったです。30インチぐらいがベストかもしれませんね。まえがき本記事はTypescriptを触ったことがある人を対象にしています。「Typescriptは使っているけど、ちゃんと使いこなせているかわからない」という人に一番しっくりくる内容だと思います。私が以前C++を触っていたこともあり、結構C++を引き合いに出しています。私がReactやReduxを触っていることもあり、オブジェクト指向よりも関数型プログラミングを意識したものになっています。はじめにTypescriptは非常に便利なツールです。Javascriptそれ自体は静的な型チェックができないため、コーディング中に実装ミスに気づきにくいのですが、Typescriptを導入することで型チェックが効くようになり、VSCodeなどのエディターを使えば補完も利用できるようになります。TypescriptはC++やJavaなどといった言語とは違い、型の定義が中途半端でも動いてしまいます。型をしっかりつけているつもりで書いていても、ちょっとしたことで信頼性がないコードができあがってしまいます。今回は型を妥協してしまっている書き方をBadケースとして例に上げ、どうすればよいかをGoodケースとして紹介していきます。※本記事はTypescript3.7時点のものです。anyは使わないTypescriptを触ったことがある人であれば、anyは知っているかと思います。極端に言ってしまうと、anyは型を付けるのを放棄したのと同義です。型を付けるための言語なのに、型を付けるのを放棄してしまっては元も子もありません。型を付けることを選んだのであれば、anyを使うことは避けましょう。Badnumberを引数に取りたいのに、anyにしてしまうとstring型でも通ってしまいます。これもokになってしまうGoodちゃんと型を定義してあげましょう。operatorと呼ばれています。これをつけることで、nullかもしれないようなものを強制的にnullじゃないものとしてみなすことができます。「ここはnullはありえないはずだから〜」という理由でよく使いがちなのですが、ありえないと思ってしまっているだけかもしれませんし、今後nullが入ってしまっても気づけなくなりますよね。そもそもnullをとらないようにしてしまうか、ちゃんと実行時にチェックをするべきです。Chainingを使うのもありです。ok}Goodちゃんと実行時にチェックしてあげましょう。nullをとらないようにしてあげましょう。keyに名前を持ち、valueに年齢を持つようなオブジェクトを定義したいとします。valueは年齢だからnumberと安直にやってしまうと、型安全が崩れてしまいます。Bad安直に上記の通りに定義してみます。undefinedこの時、山田さんのデータは入っていますが、鈴木さんのデータは入っていないため、鈴木さんの年齢はundefinedとして返ってきます。Typescript的にはエラーと認識してくれません。Goodkeyが予め予測可能なものであれば、keyを定義しておきましょう。number>'.(2339)idなど、keyが事前に定義不能な場合は、valueにundefinedも定義しておきましょう。asは使わない以下のような定義があったとしましょう。number}これは、オブジェクト指向でいう基底クラスと派生クラスの関係に近いです。使うことで継承のようなものを表現することができます。ここで問題なのが、asを使うことでこれら2つの型が双方向にキャストできてしまうということです。Bad例えば、以下のようなアップキャストは問題なく行なえます。1元のderivedにはxが含まれているので何も問題ありませんね。次はダウンキャストです。undefinedbaseにはyが無いのに、エラーなく実行されてしまいます。asを使うとダウンキャストがすんなりできてしまいます。Goodではどうすればよいのか。いえ、どうもしなくていいんです。そもそもTypescriptが提供するものはただの型です。継承といっても、カプセル化や関数のオーバーライドなどはありません。そもそもキャストする必要がないのです。引数に基底クラスを受け、条件に応じて派生クラスに変換し結果を返したいようなケースはありますよね。それを次に説明します。Literalを使いこなす以下のような、CircleとSquareという型があるとします。number}これはどちらも図形ですね。Typesを使うことで、異なる2つの型を1つの型として扱うことができます。Squareこれは、派生クラスと派生クラスから基底クラスを作るようなものです。C++から入った僕は非常に理解に苦しみました。Typescript恐ろしい。Badこのようにすることで、例えば以下のように図形を引数にその面積を返すような関数が定義できます。figure")}あれ?なんか奇妙ですよね。上記の例では、図形に特定のプロパティがあるかどうかで図形を判定し、面積を計算しています。これって気持ち悪いですよね。Triangleという型が追加になると、Triangleもheightを持つので、条件式を見直さなければならなくなります。「クラスを使ってメンバ関数で計算しろよ」って言われそうですが、クラスにしなくてもオブジェクトにちょこっと細工することで解決できちゃうんです。(なぜクラスを頑なに使わないのか、React/Redux使いの人なら知ってるかと思いますが、その理由はまたいつか機会があれば記事書きます。定義しておけばよいです。number}こうすることで、プロパティの存在によってif文を分けなくても、kindというkeyによってswitch文で処理を分けることができるようになります。アクセスしようとするとエラーになります。}}Typescript賢すぎる!最後にいかがでしたでしょうか。Typescriptは非常に便利なツールですが、使いこなすにはいくつかコツがいりますし、正直難しいです。今回挙げた内容もTypescriptができることのほんの一部に過ぎません。使いこなせれば非常に便利なツールです。こんなことできるかな?と思ったことが大抵できますので、是非いろいろ試してみてください。よる「JSXとvirtual-domで遊ぶ」です。「テックの力を最大化する」をミッションに掲げ、ヒトとテクノロジーの架け橋となるサービスを提供します。upLoginユーザーは見つかりませんでした。