TypeScriptに入門してみる
せっかくなのでTypeScriptも併せて導入してみようということでまとめてみようと思います。
TypeScriptとは
TypeScriptはMicrosoftが開発したプログラミング言語です。
いわゆるAltJSと言われるプログラミング言語群の一つで、コンパイルすると生のJavaScriptが生成されます。
JavaScriptは動的型付け言語であるため、実行時に型が決まります。逆に言うと実装時は型を気にせずに書けてしまいます。
これは予期せぬ挙動に繋がりかねない大きな欠点です。言語によっては暗黙の型変換が行われたりして意図しない結果が出力されることもあります。
JavaScriptのこうした欠点を補完するのがTypeScriptです。つまり静的型付けを行うことができ、型安全性を保つことができます。
誤った型を代入しようとするとコンパイル時にエラーが出るため、バグを未然に防ぐことができます。
近年は静的型付け言語の方が人気が高い印象です。
TypeScriptのGithubを見てみてもスター数は86.8kとその人気の高さが伺えます。
TypeScriptの型について
ここからはTypeScriptにおける型についてまとめていきます。
プリミティブ型
JavaScriptにおけるプリミティブ型もそのまま使えます。型が異なる変数を代入することはできません。
const hoge: string = 'hogehoge'; const fuga: number = hoge; // Type 'string' is not assignable to type 'number'.
ちなみに上記の変数hoge
はno-inferrable-typesをONにしているとエラーになります。
型推論できるものは省略しましょうということみたいです。
リテラル型
以下のように書くとどうなるでしょうか。
const hoge: 'fuga' = 'fuga';
こうすると変数hoge
はfuga
型となり、fuga
以外の型が入れられません。このような型をリテラル型と言います。
なので↓はNGです。
const hoge: 'fuga' = 'piyo'; // Type '"piyo"' is not assignable to type '"fuga"'.
リテラル型はプリミティブ型の部分型なので対応するプリミティブ型の変数に代入できます。
const hoge: 'fuga' = 'fuga'; const piyo: string = hoge;
オブジェクト型
オブジェクトを型に指定することもできます。
type hoge = { fuga: string, piyo: number }; const hogehoge: hoge = { fuga: 'fugafuga', piyo: 10 }; const hogefuga: hoge = { fuga: 100, // Type 'number' is not assignable to type 'string'. piyo: 10 }; const fugapiyo: hoge = { bohe: 'bohebohe', // Type '{ bohe: string; paya: string; }' is not assignable to type 'hoge'. paya: 100 };
オブジェクト型を定義するには上記のようにtype
を使う方法とinterface
を使う方法があります。
interface hoge { fuga: string, piyo: number }
interface
はオブジェクトとクラスの型のみ定義できますが、type
はそれ以外の型も定義できます。
調べてみるとinterface
を使った例の方が多そうですが、個人的にはオブジェクト型であればどちらでも良い気がします。
詳しい解説はこちらの記事がわかりやすかったです。
interfaceとtypeの違い、そして何を使うべきかについて
クラス型
先程クラスの話が少し出てきたのでクラス型にも触れたいと思います。
JavaScriptではES2015から他のオブジェクト指向言語と同様にクラスが使えるようになりましたが、TypeScriptではクラスを定義すると同時に型も定義されます。
class Hoge { fuga(): string { return 'fugafuga'; } }
こうするとstring
型を返す関数fuga
を持つHoge
というクラス型が定義されます。
ちなみに以下のようなことも可能です。
interface Hoge { fuga: () => string; } class Hogehoge { fuga(): string { return 'fugafuga'; } } const hogeClass: Hoge = new Hogehoge();
変数hogeClass
はinterface
で定義したHoge
というオブジェクト型になります。Hoge
型はstring
型を返すfuga
という名前の関数型のプロパティを持つオブジェクト型です。
ここでHogehoge
というクラスはstring
型を返すfuga
という関数を持つため、Hogehoge
型とHoge
型は同じです。
そのため、Hoge
型の変数にHogehoge
クラスのインスタンスを代入することができます。
ユニオン型
TypeScriptにはユニオン型と呼ばれる型があります。以下のようなものです。
type hoge = string | number;
hoge
型にはstring
型またはnumber
型の値が入ります。
先程のリテラル型もユニオン型にすることができます。
type hoge = 'fuga' | 'piyo';
こうするとhoge
型の変数にはfuga
かpiyo
しか入りません。Enum型に近いものになります。
(TypeScriptにもEnum型はあるのですがあまり推奨されないようです。詳しくはこちら)
タプル型
タプル型は(厳密な理解ではないですが)要素の型と要素数が指定された配列型と理解しています。以下のように書きます。
type hoge = [string, number, boolean]; const fuga: hoge = ['fugafuga', 100, true]; const piyo: hoge = [1, 2, false]; // Type 'number' is not assignable to type 'string'.
例えばPromise.all()
で複数の値が返ってくる関数の返り値の型に使ったりできます。
他には配列の要素数が決まっている場合等にも使えそうです。
タプル型は可変長にすることができ、
type hoge = [string, ...string[]]; const fuga: hoge = ['fuga', 'fugafuga']; // OK const piyo: hoge = ['piyo']; // OK const poyo: hoge = []; // NG const bohe: hoge = [1]; // NG const mohe: hoge = ['mohe', 10]; // NG
hoge
型はstring
型の要素が最低1つ、残りの要素もすべてstring
型で長さは可変長という型になります。
また以下のような書き方もできます。
type hoge = [string, string?]; const fuga: hoge = ['fuga', 'fugafuga']; // OK const piyo: hoge = ['piyo']; // OK const poyo: hoge = ['poyo', 'poyopoyo', 'poyopoyopoyo']; // NG
この場合、2つ目の要素はオプションであっても無くてもOKですが、先程の可変長と異なり3つ目の要素を入れようとするとエラーになります。
まとめ
以上、TypeScriptの型についてざっくりまとめてみました。
まだ全てを理解して使いこなすには程遠いですが少しずつ入門していきたいと思います。
ちなみに以下のサイト・記事がわかりやすかったので参考にしました。