JavaScriptのきほんを学ぼう
■第11話:TypeScriptのクラス
(最終更新日:2023.07.30)

(絵が小さい場合はスマホを横に)
「TypeScriptでもクラスを使いたい!」
前回ご紹介したように、ES6からJavaScriptでもクラスが使えるようになった。
しかし、元々はプロトタイプベースの言語を糖衣構文として利用できるようにしたため、クラスの機能としては最低限しかない。
もっと便利な機能をもったクラスを使うのであれば、TypeScriptを用いることが必要である。
TypeScriptはJavaScriptに実装されてる機能に加え、本来クラスで必要な機能を大体兼ね備えている。
今回はそんなTypeScriptのクラスについて説明する。
1. TypeScriptのクラスの型
クラスに限らないが、TypeScriptでは型を指定することができる。
これにより、予期せぬ値(数字と文字、NullやNaN)の混入を防ぐことができ、それに伴う不具合を未然に防ぐ。
定義できる型としては「string, number, boolean, null, undefined, void」などがある。
これに加えて、文字列リテラルとユニオン型、ジェネリクス、オプションプロパティなどの型や機能がある。
これらの型はどれも、入力できる値を制限して、エラーを防ぐ役割を果たす。
下記は前回用いたJavaScriptのクラスに型を追加したものだ。Field(変数)のcontentやtaiyakiなどにstring(文字列)を使うことを強制している。
そしてエラーを未然に防ぐだけでなく、どんな値が入るのかがある程度分かるので、コードが読みやすくなるというメリットもある。
TypeScriptのクラスの型
2. アクセス修飾子(public, protected, private)
前回、JavaScriptのクラス内でもプライベートとパブリックを定義できることは説明した。
しかしながら、privateの使い方としてはFieldやmethod(関数)名に#を付けるという、少し強引なやり方であった。
TypeScriptではアクセス修飾子というものが用意されていて、その修飾子を用いることで明示的にアクセス権限を書くことができる。
publicを使えばクラスの外からでも、protectedを使えばそのクラスか継承先のクラスで、privateはそのクラス内だけに限定して使うことができる。
以下に例を示す。taiyakiにprivateを付けているため、
クラスの外から呼び出そうとした一番最後のconsole.logの行でエラーが発生している。
このように、アクセス修飾子を用いることでアクセスの範囲を制御できる。
TypeScriptでprivateを用いる
3. readonly、static
TypeScriptには上記のアクセス修飾子以外にも、アクセス方法を制限できるreadonlyとstaticがある。 readonlyは文字通りconstructorでFieldの値を指定する以外は、値の変更をさせないようにすることができる。 下記はconstructorでtaiyakiに「たい焼き」を指定した後、impressionメソッド内で「磯辺焼き」に変えようとして、エラーしている。 このように、fieldの値の変更を防ぐことができる。
TypeScriptのreadonlyの使い方
一方、staticはnewを用いてインスタンスを生成しなくても、直接クラスのfieldやmethodにアクセスすることを可能にする。 下記コードの後ろから2行目でTaiyakiクラスのtaiyakiフィールドに直接アクセスできていることが分かると思う。 しかし、constructorの値も変わってしまったため、一番最後の行でmattyaTaiyakiインスタンスからtaiyakiフィールドにアクセスしてもエラーしてしまっている。 どうしても必要な場合以外はstaticは使わず、インスタンスを生成した方が良いだろう。
TypeScriptのクラスのstatic(field)
また、methodに関しても同様にアクセスができる。testメソッドにstaticを指定したため、 一番最後の行でTaiyakiクラスから直接testメソッドにアクセスすることが可能になっている。 consoleには2が表示される。
TypeScriptのクラスのstatic(method)
4. interface
interfaceとは「fieldやmethodでこういう名前でこういう型のものを使いますよ」という宣言のようなものである。
そのため、interfaceから直接インスタンスを生成して使うこということはできない。
加えて、宣言したフィールドとメソッドを使い忘れても、エラーが発生する。これは、interfaceで定義した通りにクラスを実装することを強制している。
interfaceは、言ってしまえばクラスの骨組みのようなものだ。これを使えば、オブジェクト指向の3つの特徴の1つである多態性も実装できる。
interfaceは下記のように、継承のextendsの代わりにimplementsでクラスに実現できる。
下記はinterfaceをクラスに実装した例である。implementsでインターフェースを指定することで実装できる。
加えてTaiyakiクラスの中では、interfaceで指定した変数を全て使っていることが分かるはずだ。
TypeScriptのインターフェースの使い方
もし、classでinterfaceで指定したフィールドを使わなかった場合は、下記のようにエラーが生じる。 priceの実装を無視したため、Taiyakiクラスでエラーの赤文字が表示されているのが分かると思う。
フィールドを実装してなくてエラー
また、指定したメソッドを使わなかった場合も同様にエラーする。 下記の場合、impressionメソッドをクラスで実装すれば、Taiyakiクラスのエラーは解消される。
メソッドを実装しなくてエラー
5. まとめ
今回、TypeScriptのクラスを説明した。 JavaScriptに比べて、オブジェクト指向として必要なクラスの機能が備わっていることが分かったと思う。 今回説明した、型、アクセス修飾子(public, protected, private)、readonly、static、interfaceは比較的良く使う部分だと思うので、 まずはここから使えるようになろう。
▼参考図書、サイト
サバイバルTypeScript typescriptbook.jp
JavaScriptのエンジニアがTypeScriptの特徴を「超」手っ取り早く大まかに把握するための本 天田史郎