TypeScriptについて、こちらの書籍で学習したことをまとめています。
イントロダクション
TypeScriptとは何なのか?JavaScriptとの違い、使用するメリットを一言で説明します。
ズバリ!
JavaScriptがコードのミスを指摘するのは、プログラムを実行したとき。
これに対し、TypeScriptは、エディタの中で、入力したときに指摘してくれる。
全体像
一言で説明しましたが、TypeScriptとは何なのか、まずは全体像を見ていきましょう!
コンパイラー
プログラムとは、テキストが書かれたファイルのことです。
このテキストは、コンパイラーによって解析され、AST(抽象構文木:空白やコメントを無視したデータ構造のこと)に変換されます。
このASTはさらに、バイトコード(よりハードウェアに近いレベルの表現)に変換されます。
このバイトコードがランタイム(別のプログラムに入力として与える)より結果を得ます。
つまり
TypeScriptはというと、、
チェックをはさみ、バイトコードでなく、JavaScriptコードへコンパイルします。
型システム
型システムには2つの種類があります。
- 構文を使って型をコンパイラーに伝える
- 型を自動的に推論する
TSはこれら2つの要素を備えています。
TSは型にアノテーションを付けることができます。
アノテーションとは、「値:型」という形式で値の型を伝えることです。
TSのアノテーションは省略することができ、できる限り省略形を使います。
TSとJSの違い
以下の3つの観点から違いを説明します。
- 型のバインド
- 型の変換
- 型のチェックタイミング
型のバインド
JSは、動的に型がバインド(関連付け)されるのでプログラムの型を知るにはそのプログラムを実行しないといけない。
それ対し、TSはプログラムを実行しなくても型を知ることができる。
型の変換
以下のコードを実行した場合の結果を比較します。
3 + [1]
JSの場合
"31"
TSの場合
エラー
TSのエラーは、あって然るべき結果ですね!
JSは親切に、型を自動変換してくれるため、上記のような結果を返します。
型のチェックタイミング
TSは実行前、入力した時点でエラーを提示してくれます。
tsconfig.json
TSを機能させるには、TSのプロジェクトのルートディレクトリに、tsconfig.jsonという名前のファイルを含んでいる必要があります。
ここにTSのコンパイルなどの情報を定義します。
設定の例がこちら
{
"compilerOptions": {
// コンパイラが想定するAPI
"lib": ["es2015"],
// コンパイルモジュールシステム
"module": "commonjs",
// コンパイラにより生成されるJSの格納フォルダ
"outDir": "dist",
// TSが動作するときデバッガーが元のTSを表示できるようにする
"sourceMap": true,
// できるだけ厳格にチェックする
"strict": true,
// コンパイルするJSバージョン
"target": "es2015"
},
// コンパイル対象のフォルダを指定
"include": [
"src"
]
}
各行の設定に補足を加えています。
tslint.json
JSの構文チェックにはESlintを使いますが、
TSの構文チェックにはTSlintというリンターを使用します。
以下コマンドでtslint.jsonを生成します。
$ ./node_modules/.bin/tslint --init
これにより以下が自動生成されます。
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {},
"rulesDirectory": []
}
例として、この中のrulesを以下のようにカスタマイズすることで、末尾のセミコロン;とカンマ,を無効とすることができます。
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"semicolon": false,
"trailing-comma": false
},
"rulesDirectory": []
}
型について
TSの目的は、例えば変数Tを見た時に、それがTであることがわかるだけでなく、そのTが何をするのかを知ることです。
それでは、それぞれの型を使って何ができるのかを見ていきたいと思います。
型の種類
型 | 説明 |
any | デフォルトの型で、全ての値の集まり。型チェックをしていないのと同じ。使用は避ける。 |
unknown | 前もって型がわからない時に使用。 |
boolean | 比較や、否定(!)で使用。 |
number | 数値 |
bigint | 大きな整数。numberは2の53乗までなので、それより大きい整数を扱う場合。 |
string | 文字列 |
symbol | オブジェクトやマップにおいて文字列キーの代わりとして使用される。 symbolは一意であり、他のどのsymbolとも等しくならない! |
object | その値がJSのオブジェクトであることだけを伝える。 |
以下に補足情報を記述しています。
unknown
let a: unknown = 30; // a > unknown
let b = a === 123; // b > boolean
let c = a + 10; // c > any aでエラーとなる。Object is of type 'unknown'.ts(2571)
unknownは、他の値と比較することはできるが、特定の値を想定した使い方はできない。
3行目の場合、aはnumberが想定されるためエラーとなります。
letとconstの違い
letとconstでは推論が異なり、constを使うとリテラル型を推論します。
boolean
let a = true; // boolean
const b = true; //true
TSでは、constで割り当てられた値は変更されることはないと認識し、最も狭い範囲で推論するので、trueとなるわけです。
number
numberでもbooleanと同じ結果となります。
let a = 123; // number
const b = 456; // 456
型レベルの演算、操作
型エイリアス
typeを使って型エイリアス(別名)を定義します。
以下の例では、変数Ageの型をnumberと宣言し、Personオブジェクトの型定義をしています。
type Age = number
type Person = {
name: string
age: Age
}
かつ、または
「かつ」を「&」で、「または」を「|」で表す。
配列
let a = [1, 2, 3]; // number[]
let b = ["a", "b", "c"]; //string[]
let c = [1, "a"]; // (string | number)[]
配列の場合は、単純な数値や文字列と異なり、末尾に[]が付きます。
viod
voidとは、「存在しないもの」を更に細かく表現したもので、何も返さない関数の戻り値の型です。
function a() {
let b = 2 + 2;
let c = b * b;
}
ここでの「a」はvoidになります。
console.logも、このvoidに当たります。
never
決して戻ることのない関数の型
function d() {
throw TypeError("always error");
}
throwしているので、neverになります。
enum
コンパイル時にキーが固定されているオブジェクトのようなものです。
enumには以下2つの種類があります。
- 数値列挙:文字列から数値へとマッピング(対応付け)
- 文字列列挙:文字列から文字列へとマッピング
enumは名前、キーともに大文字で始めるのが慣例
enum Language {
English,
Japanese,
Chinese,
}
各キーの値が自動的に、0, 1, 2と推論されます。
enumから値の取得
通常のオブジェクトから取得するのと同じです。
let myLanguage = Language.English; // Language
まとめ
まずは、JavaScriptとの違い、使うことによるメリット、全体像を把握することができ、抵抗無くTypeScriptにエントリーできたのではないでしょうか!
ちょこちょこギャグも挟みユーモアもある、わかりやすい書籍ですのでおすすめです。
コメント