【技術書まとめ】プログラミングTypeScript

# 感想

日頃TypeScriptを使っていたので読むことで知識が整理された。


![スクリーンショット 2021-09-18 22.56.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/9eb89da1-9173-97bf-a17c-975040b02bf6.png)


# 1章 イントロダクション

- 型安全性（type safety）
    - 入力したときにエラーメッセージをくれる
        - JSは実行時にくれる


# 2章 TypeScript: 全体像

- コンパイラー
    - ![スクリーンショット 2021-09-21 8.08.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/ec8b32e2-edfc-84aa-5572-2a4813b54ccf.png)
    - やってくれること
        1. 書いたプログラムを抽象構文木（AST: abstract syntax tree）に変換する
            - 空白、タブ、改行やコメントを無視したデータ構造
        1. ASTをバイトコードにコンパイルする
        1. バイトコードをランタイムに与える
    - TypeScript
        1. TSソースが TypeScript AST になる
        1. AST が型チェックされる
        1. 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"`はエラーにならない
- コードエディターのセットアップ
    - tsconfig.json
        - include
            - どのフォルダを探すか
                - `"src"`
        - lib
            - どのAPIが存在しているとTSCが想定すべきか
                - `"ex2015"`
        - module
            - コードをどのモジュールシステムにコンパイルすべきか
                - `"commonjs"`
        - outDir
            - 生成するJSコードをどのフォルダーに格納すべきか
        - strict
            - すべてのコードが型付けされていることを強制する
        - target
            - TSCがコードをどのJSバージョンにコンパイルすべきか
                - `"es2015"`
    - tslint.json
        - `./node_modules/.bin/tslint --init`で作成する


# 3章 型について

- 型とは
    - 「値と、それを使ってできる事柄の集まり」
        - boolean型なら`true`と`false`と演算や操作（`||, &&, !`）の集まり
    - ![スクリーンショット 2021-09-22 8.01.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/68a19624-7cb5-3231-189d-46332a3a346b.png)
    - 型アノテーション
        - 明示的な型の指定
            - 例えば引数に型アノテーションがあると入力値に型の制約を与えることができる
    - リテラル型
        - 「ただ1つの値を表し、それ以外の値は受け入れない型」
            - `const c = true`
            - `let e: true = true`
    - オブジェクト型
        - `[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は関数を呼び出さない
            - バインドして新しい関数を返してくる
- 関数そのものの型
    - `(a: number, b: number) => number`
        - 呼び出しシグネチャ、型シグネチャと呼ばれる
- 型駆動開発
    - まず型を決める
        - 引数や返り値


# 5章 クラスとインターフェース

- アクセス修飾子
    - public
        - どこからでもアクセスできる。デフォルトのアクセスレベル
    - protected
        - そのクラスとサブクラスのインスタンスからアクセスできる
    - private
        - そのクラスのインスタンスからのみアクセスできる
- 返り値に`this`にすることもできる
    - サブクラスで返り値の変更だけのオーバーライド書き換えが必要がなくなる
- 型とインターフェイスの違い
    - 型は右辺に任意の型を指定できる
    - インターフェイスは拡張する時に拡張元に割り当て可能か確認してくれる
    - インターフェイスは同じスコープ内に同じ名前のインターフェイスがあると自動的にマージされる
        - 宣言のマージ
- `implements`で特定のインターフェイスを満たしていることを表現できる
- インターフェースと抽象クラスどちらを使うか
    - 複数クラス間で実装共有するときは抽象クラス
    - 「このクラスはTである」と軽量に表現するときはインターフェース
        - インターフェースはJSコードを発行せず、コンパイル時のみ存在する
            - 抽象クラスはJSのクラスなのでコードを発行する
- TSはクラスを名前でなく構造で比較する
    - 名前はzebraでもpoodleでもいい
- ポリモーフィズム
- ミックスイン
- デコレーター


# 6章 高度な型

- 変性
    - 型が`number | undefined`に`string | number | undefined`は渡せない
        - 共変(covariant）
            - 逆は可能
- 割り当て可能性
    - OK
        1. `A <: B`である
        1. A が any である
- 型の拡大
    - `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 FriendList = APIResponse['user']['friendList']`でGraphQLから受け取った値から型を取得できる
- ユーザー定義型ガード
    - `a is string`
        - typeof で型を判定して boolean を返す関数の返り値につけると型が引き継がれる
            - `isLegacyDialog`などの判定をする関数で使える
- 名前的型をシミュレートするブランド型
    - `CompanyID`と`OrderID`は中身は違うが同じ`string`
        - TSはわからない
            - `type CompanyID = string & {readonly brand: unique symbol}`
                - 大規模なアプリケーションで効果がある

# 7章 エラー処理

- 何かが失敗したことを単に知らせる
    - nullを返す
- なぜ失敗したのか情報を与える
    - 例外をスローする
    - 例外を返す
- 起こりうる全ての例外を明示的に処理するよう利用者に強制する
    - 例外を返す
- エラー処理のボイラープレートを少なくする
    - 例外をスローする
- エラーを組み立てる方法を必要とする
    - Option


# 8章 非同期プログラミングと並行、並列処理

- JSのイベントループ
    - ![スクリーンショット 2021-10-18 8.27.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/9de69803-7a3c-936f-08ce-e41d69103793.png)
- エミッター
    - ![スクリーンショット 2021-10-20 8.10.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/aeb01074-8924-1d19-d23d-5ca7cd94bbae.png)
- テクニック
    - シンプルな非同期タスク
        - コールバック
    - 複数のタスクを直列または並列に並べる
        - Promiseやaync/await
    - 何度も発火するイベント
        - イベントエミッターやRxJS
    - 複数スレッドで行う
        - 型安全なAPIなどを使う


# 9章 フロントエンドとパックエンドのフレームワーク

フレームワークの説明など


# 10章 名前空間とモジュール

- JSのモジュールの歴史
    - 最初はモジュールシステムは一切なかった
        - すべてがグローバルの名前空間
            - 変数名の競合や使い果たしが起こる
- 名前空間とモジュールでカプセル化を迷うときはモジュールを選ぶ



# 11章 JavaScriptとの相互運用

- 型宣言
    - `.d.ts`
        - `.ts`から型だけ抜き出したもの
            - 実装を含まない
    - 「JSに定義されたこのようなものが存在しており、それについて私が説明します」とTSに伝えるための方法
        - アンビエント
- JSからTSへの移行方法
- TSからJSを使用する方法
    - ![スクリーンショット 2021-10-28 8.11.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282504/ed70752f-7c40-155a-7afb-879babe885b7.png)



# 12章 TypeScriptのビルドと実行

ビルドするときの注意点など