感想
日頃TypeScriptを使っていたので読むことで知識が整理された。
1章 イントロダクション
- 型安全性(type safety)
- 入力したときにエラーメッセージをくれる
- JSは実行時にくれる
- 入力したときにエラーメッセージをくれる
2章 TypeScript: 全体像
- コンパイラー
- やってくれること
- 書いたプログラムを抽象構文木(AST: abstract syntax tree)に変換する
- 空白、タブ、改行やコメントを無視したデータ構造
- ASTをバイトコードにコンパイルする
- バイトコードをランタイムに与える
- 書いたプログラムを抽象構文木(AST: abstract syntax tree)に変換する
- TypeScript
- TSソースが TypeScript AST になる
- AST が型チェックされる
- TypeScript AST が JavaScript ソースとなる
- この後、コンパイルされた JavaScript が V8エンジンなどによって JavaScript AST となる
- AST がバイトコードとなる
- バイトコードがランタイムによって評価される
- 「TypeScript から JavaScript へコードをコンパイルするときに、TSCは、プログラマーが書いた型は見ない」
- 型チェックのためだけに使われる
- 型を書き換えてもアプリケーションは壊れない
- 型チェックのためだけに使われる
- 型システム(type system)
- TypeScript は漸進的型付き言語(garadually typed language)
- 型がすべてわかっていればベターだが、すべてわかっていなくても推論でミスを見つけてくれる
- 正しそうに見えないことをするとTSはエラーを出し、意図をはっきりさせると手を引く
-
3 + [1]; // "31"
はエラー-
(3).toString() + [1].toString() // "31"
はエラーにならない
-
-
- TypeScript は漸進的型付き言語(garadually typed language)
- コードエディターのセットアップ
- tsconfig.json
- include
- どのフォルダを探すか
"src"
- どのフォルダを探すか
- lib
- どのAPIが存在しているとTSCが想定すべきか
"ex2015"
- どのAPIが存在しているとTSCが想定すべきか
- module
- コードをどのモジュールシステムにコンパイルすべきか
"commonjs"
- コードをどのモジュールシステムにコンパイルすべきか
- outDir
- 生成するJSコードをどのフォルダーに格納すべきか
- strict
- すべてのコードが型付けされていることを強制する
- target
- TSCがコードをどのJSバージョンにコンパイルすべきか
"es2015"
- TSCがコードをどのJSバージョンにコンパイルすべきか
- include
- tslint.json
-
./node_modules/.bin/tslint --init
で作成する
-
- tsconfig.json
3章 型について
- 型とは
- 「値と、それを使ってできる事柄の集まり」
- boolean型なら
true
とfalse
と演算や操作(||, &&, !
)の集まり
- boolean型なら
- 型アノテーション
- 明示的な型の指定
- 例えば引数に型アノテーションがあると入力値に型の制約を与えることができる
- 明示的な型の指定
- リテラル型
- 「ただ1つの値を表し、それ以外の値は受け入れない型」
const c = true
let e: true = true
- 「ただ1つの値を表し、それ以外の値は受け入れない型」
- オブジェクト型
-
[key: T]: U
はインデックスシグネチャ- オブジェクトに任意の数のプロパティを持たせられる
-
let a: { [key: number]: boolean }
で a は boolean である数値プロパティを任意の数持てる
-
-
key: T
はnumber
かstring
のどちらかでないといけない
- オブジェクトに任意の数のプロパティを持たせられる
-
let user: { readonly firstName: string }
で読み取り専用にできる- オブジェクトの
const
のようなもの
- オブジェクトの
-
- union型とintersection型
-
type CatOrDogOrBoth = Cat | Dog
はどちらか1つであるとは限らない- unionなので同時に両方になれる(CatかつDog)
-
- 配列
-
T[]
とArray<T>
はまったく同じ
-
- タプル
- 配列よりも安全
- 不均一のリストを安全にコード化できる
- 長さを限定できる
- 配列よりも安全
- 「値と、それを使ってできる事柄の集まり」
4章 関数
- call, apply, bind
add(10, 20) // 30
-
add.apply(null, [10, 20]) // 30
- nullをthisにバインドして配列を引数として展開する
-
add.call(null, 10, 20) // 30
- callは順番に適用する
-
add.bind(null, 10, 20)() // 30
- bindは関数を呼び出さない
- バインドして新しい関数を返してくる
- bindは関数を呼び出さない
- 関数そのものの型
-
(a: number, b: number) => number
- 呼び出しシグネチャ、型シグネチャと呼ばれる
-
- 型駆動開発
- まず型を決める
- 引数や返り値
- まず型を決める
5章 クラスとインターフェース
- アクセス修飾子
- public
- どこからでもアクセスできる。デフォルトのアクセスレベル
- protected
- そのクラスとサブクラスのインスタンスからアクセスできる
- private
- そのクラスのインスタンスからのみアクセスできる
- public
- 返り値に
this
にすることもできる- サブクラスで返り値の変更だけのオーバーライド書き換えが必要がなくなる
- 型とインターフェイスの違い
- 型は右辺に任意の型を指定できる
- インターフェイスは拡張する時に拡張元に割り当て可能か確認してくれる
- インターフェイスは同じスコープ内に同じ名前のインターフェイスがあると自動的にマージされる
- 宣言のマージ
-
implements
で特定のインターフェイスを満たしていることを表現できる - インターフェースと抽象クラスどちらを使うか
- 複数クラス間で実装共有するときは抽象クラス
- 「このクラスはTである」と軽量に表現するときはインターフェース
- インターフェースはJSコードを発行せず、コンパイル時のみ存在する
- 抽象クラスはJSのクラスなのでコードを発行する
- インターフェースはJSコードを発行せず、コンパイル時のみ存在する
- TSはクラスを名前でなく構造で比較する
- 名前はzebraでもpoodleでもいい
- ポリモーフィズム
- ミックスイン
- デコレーター
6章 高度な型
- 変性
- 型が
number | undefined
にstring | number | undefined
は渡せない- 共変(covariant)
- 逆は可能
- 共変(covariant)
- 型が
- 割り当て可能性
- OK
-
A <: B
である - A が any である
-
- OK
- 型の拡大
-
const a = 'x' // x
でlet b = a // string
となる-
const c: 'x' = 'x'
なら拡大されない
-
-
null, undefined
で初期化された変数がスコープを離れると明確な型が割り当てられる
-
- 型の絞り込み
- type というタグをつける
-
type UserTextEvent = {type: 'TextEvent', value: string, target: HTLInputElement}
など-
if (event.type === 'TextEvent') {...
で判定するとTSは中身を全て型判定してくれる-
type UserEvent = UserTextEvent | UserMouseEvent
の時でも
-
-
-
- type というタグをつける
- ルックアップ型
-
type FriendList = APIResponse['user']['friendList']
でGraphQLから受け取った値から型を取得できる
-
- ユーザー定義型ガード
-
a is string
- typeof で型を判定して boolean を返す関数の返り値につけると型が引き継がれる
-
isLegacyDialog
などの判定をする関数で使える
-
- typeof で型を判定して boolean を返す関数の返り値につけると型が引き継がれる
-
- 名前的型をシミュレートするブランド型
-
CompanyID
とOrderID
は中身は違うが同じstring
- TSはわからない
-
type CompanyID = string & {readonly brand: unique symbol}
- 大規模なアプリケーションで効果がある
-
- TSはわからない
-
7章 エラー処理
- 何かが失敗したことを単に知らせる
- nullを返す
- なぜ失敗したのか情報を与える
- 例外をスローする
- 例外を返す
- 起こりうる全ての例外を明示的に処理するよう利用者に強制する
- 例外を返す
- エラー処理のボイラープレートを少なくする
- 例外をスローする
- エラーを組み立てる方法を必要とする
- Option
8章 非同期プログラミングと並行、並列処理
- JSのイベントループ
- エミッター
- テクニック
- シンプルな非同期タスク
- コールバック
- 複数のタスクを直列または並列に並べる
- Promiseやaync/await
- 何度も発火するイベント
- イベントエミッターやRxJS
- 複数スレッドで行う
- 型安全なAPIなどを使う
- シンプルな非同期タスク
9章 フロントエンドとパックエンドのフレームワーク
フレームワークの説明など
10章 名前空間とモジュール
- JSのモジュールの歴史
- 最初はモジュールシステムは一切なかった
- すべてがグローバルの名前空間
- 変数名の競合や使い果たしが起こる
- すべてがグローバルの名前空間
- 最初はモジュールシステムは一切なかった
- 名前空間とモジュールでカプセル化を迷うときはモジュールを選ぶ
11章 JavaScriptとの相互運用
- 型宣言
-
.d.ts
-
.ts
から型だけ抜き出したもの- 実装を含まない
-
- 「JSに定義されたこのようなものが存在しており、それについて私が説明します」とTSに伝えるための方法
- アンビエント
-
- JSからTSへの移行方法
- TSからJSを使用する方法
12章 TypeScriptのビルドと実行
ビルドするときの注意点など