typescript勉強メモ


udmy勉強材料：[Understanding TypeScript](https://www.udemy.com/course/understanding-typescript/)

目次
- [typescriptのcore types](#typescriptのcore-types)
- [コンパイルとプロジェクト環境設置](#コンパイルとプロジェクト環境設置)
- [next generation javascript & typescript](#next-generation-javascript-and-typescript
)
- [classes and interface](#classes-and-interface)
- [advance type](#advance-type)
- [generics](#generics)
- [decorator](#decorator)
- [module namespace](#module-namespace)
- [webpack](#webpack)
- [3rd party libraries](#3rd-party-libraries)
---------


- TypeScriptはブラウザで支持されていない、あくまでJSコード書くツールとして使用されている
  - TypeScriptはstatic types、コード書く時宣言が必要。JSはdynamic type、ブラウザ上走る時では変更できる
  - ローカル環境にnode.jsをインスドール、そしてプロジェクトフォルダーに`npm init` と`npm install --sava-dev lite-server`コマンド入力し、簡単な環境を構築

##### typescriptのcore types
- typescriptのcore types
  
  - TypeScriptのprimitive typesは全部lowercase（string、number。。。）
  - letでは再宣言が禁止、値のtypeを変更出来ないが内容値が変更できる。constではtype再宣言、内容値再代入が禁止
  - typescript中でobject typeを作成できるが、JSではobject typeが無い為、へコンパイル後定義済の結果のみ残される
    ```
    const person: {
      name: string;
      age: number;
    } = {
      name: 'Maximilian',
      age: 30
    };
    ```

  - `tuple`を使って、確定の順番である複数のtypeを含むarrayを定義、例えば`role: [number, string]`、一番がnumber、二番がstringのarray

  - TypeScriptのenum typeを定義できる、`enum Role {ADMIN = 5, READ_ONLY, AUTHER};`；enumの値はnumberがついている、Roleはcustome typeなので、イニシャル文字uppercaseが必要
    - 最初のnumberが与えられた場合、後ろのちのnumberは自動加算される
    - 手動でnumberつけるもできる
    - number以外、stringも使用できる

  - union typeでparameterのtypeを複数定義、　`input1: number | string`
  - literal typeでparameterを同じtypeの下で、複数選択を定義、`input3: 'as-number' | 'as-text'`
  - Type Aliasesでcustome typeを定義でき、重複なコードを避ける、`type User = { name: string; age: number };  const u1: User = { name: 'Max', age: 30 };`
  - TypeScriptではfunctionのresultを`void`に設定できる、何も返さない場合は`void`を使用。

  - functionはtypeの一つ、マウスをfunctionに当てると、返されるresultの結果が見れる。
  ![スクリーンショット 2023-10-22 19.56.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/c30f7434-8d74-b5da-d921-3a237b1c6e39.png)
    - 返されるresultの結果を設定できる`function add(n1: number, n2: number): number {}`
    - () =>でfunctionの形を定義、`let CombinValues: (a: number, b: number) => number;  CombinValues = add;`
    - call back function
    ![スクリーンショット 2023-10-22 20.34.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/05539301-4bd4-2e0a-8224-24fb811b4816.png)

  - `unknow`と`any`と違う、 anyはtypeのチェックを回避できるが、unkowmは今のデータtypeをチェックする。以下の例ではunknowはエラーが出る、anyはでない
  ![スクリーンショット 2023-10-22 20.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/063d8f6e-015e-727d-83ba-966d5e403b95.png)
  - functionの中で`throw`を使い、ブラウザ上エラーを投げる。この場合、返す resultは`never`
  ![スクリーンショット 2023-10-22 20.59.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/1344d1b8-68bc-a63c-29cf-9618c9245edd.png)


##### コンパイルとプロジェクト環境設置

- 毎回tsファイルを保存後、`tsc fileName.ts`でコンパイル必要があるが、`tsc fileName.ts -w（或いは--watch）`でwatch modeを開始。目標ファイルが更新される度、コンパイルが自動実行、watch modeから離れる場合は`control + c`
  - プロジェクト全体をTypeScriptで管理したい場合、プロジェクトフォルダー下で`tsc --init`（このコマンドはプロジェクト毎一回のみ）
    - `tsc`コマンドで全てのTypeScriptファイルを一気にコンパイルできる
    - `tsc -w`でプロジェクト全体をwatch modeに入る

- TypeScriptプロジェクトの設定ファイルtsconfig.jsonの中、
  - TSの管理から除外したいファイルのpathを追加できる。
    - `node-modules`（開発資材保有のフォルダー）が黙認上除外される
    - `include`と一緒にを使って、柔軟に管理したいファイルやフォルダーを設置
  ![スクリーンショット 2023-10-23 8.21.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/b89b7ebd-2725-f21d-7743-02edcdbee5a0.png)

  - `target`でコンパイルのJSバージョンを決める
  - `lib`は黙認上`target`に設置されたバージョンと関連している
  - `sourceMap`をtureにすると、ブラウザconsole画面でTypeScriptのソースが見れる
![スクリーンショット 2023-10-23 8.54.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/4f67b681-1840-dd4a-8a58-419ddfe75fd6.png)

- `outDir`でコンパイル後のjsファイルの保存先を指定できる
  ![スクリーンショット 2023-10-23 17.42.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/0f48730a-0a6e-533b-52fe-3e6bddfea133.png)

- `rootDir`でコンパイルしたいtsファイルの保存先を指定できる
  ![スクリーンショット 2023-10-23 17.48.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/70836c2e-ae14-3b9f-efee-d19ca6158d2b.png)

- `noEmitOnError`をtrueにすると、tsファイルの中エラーがある場合、jsファイルが作成されない；falseにすると、エラーがある場合、jsファイルが作成される
  ![スクリーンショット 2023-10-24 17.20.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/8afc67e6-d596-ea55-0459-f995341f8b36.png)

- `strict`下の設置は黙認strictと同じ、それぞれ単独設定できる
  ![スクリーンショット 2023-10-24 17.25.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/225c3323-5548-9bd0-5526-7a1709e32b89.png)
  - `noImplicitAny`はfunctionが作成された時、functionに渡すparameterがtype宣言必要の設置
    ![スクリーンショット 2023-10-24 17.31.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/8e2bb631-220e-c20f-9412-10c351f7c949.png)


##### next generation javascript and typescript
node.jsをインスドールし、簡単なローカルサービスを走るため、`npm install`と`npm start`コマンド

- 以下URLで最新のJavascript機能を確認
  https://compat-table.github.io/compat-table/es6/

- `{}`内で定義されたparameterは{}外部使用できない、例えばfunction　{}、if　{}

- `=>`の使用はfunctionの定義を簡単にする
  ![スクリーンショット 2023-10-24 19.50.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/eebd3da3-bfa7-cbd2-b47a-07cb7374ee1a.png)

- `...`でarrayやobjectに内容を追加
  ![スクリーンショット 2023-10-24 20.04.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/cbc46e10-c56d-a7e1-de90-4ac1a20f9425.png)
  - `...`を複数paramaterを指す
    ![スクリーンショット 2023-10-24 20.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/135afbf8-96d4-8560-a594-9deef858addb.png)

- objectのparameterを引き出し、新しい値を与えることができる
  ![スクリーンショット 2023-10-24 20.21.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/fe668e07-ad99-a7ea-2db8-37d2cc54e18d.png)


##### classes and interface
- typescriptの中では readonly を使って、初期化されたpropertyの値が変更され無い様にする、例えば private readonly ID
  - readonlyはabstract classとinterfaceの中にも使用できる
- abstract methodの定義例、abstract discribe(this: Department): void;
  abstract methodを使うできるのは、abstract classの内部
- 新規classをabstract　classから作成の時、extends出来るabstract　classは一個のみ
  - 新規classは自動的にabstract　classのpropertyとmethodを持つ
- interfaceは複数のinterfaceをextends出来る
- 新classをinterfaceから作成の時、implements出来るinterfaceは複数可能
  - 新規classはinterfaceのpropertyとmethodを定義する必要がある
- interfaceでfunctionを定義できる、例として
  type AddFun = (a: number, b: number) => number;  //typeで定義
  interface AddFun { (a: number, b: number): number; }  //interfaceで定義
- interfaceとclassの中、存在任意のpropertyの定義は？を使用、例として `name:? string `


##### advance type
- 複数のtypeをcombineできる、例として type ElevatedEmployee = Admin & Employee;（AdminとEmployeeは二つのtype）
- TypeScriptでは、`.getElementById()`から取得したhtmlコンポーネントの種類が知ら無い、しれを確定するため、以下二種のコードを使う、`!`の用途はnullでは無いを指定
  `const userInputElement = <HTMLInputElement>document.getElementById('user-input')!；`
  `const userInputElement = document.getElementById('user-input')! as HTMLInputElement；`

- run timeエラーを回避するため、optional chainingの特性を使用、データの存在を確認、例として console.log(fetchedUserData?.job?.title);


##### generics
- `const names : any[] = [];` = `const names : Array<any> = [];`
  <>の内容はTypeScriptにデータの種類を伝える、そうすると、コード書く時TypeScriptからのチェックとサポートが貰える

- generic typeをextendし、その内容の範囲を設定できる、例として 
  `function count<T extend Lengthy>(element : T) {}`
  - ここのextendは、後ろにいるobjectやinterfaceから作成されたobjectやinterfaceではなく、後ろにいるobjectやinterface中に含まれるpropertyを持つobjectやinterfaceでいい、
  例として `interface Lengthy {length: number;}`を定義し、上記elementに['text1', 'text2']のlistを渡すのはOK


##### decorator
- tsconfig.jsonのexperimentalDecoratorsをtrueにする
  ![スクリーンショット 2023-11-01 17.12.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/ddec84a0-b98e-854a-09c4-d09cac1ffa86.png)

- classにdecoratorを設置：calssの上一行`＠`付けのfunctionを設置。decoratorの起動条件は、 classがJSに認識された時、インスタンスが作成された時ではない
  ![スクリーンショット 2023-11-01 17.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/5057704d-1858-bf18-dd8a-69cae380fbb9.png)

- decoratorはfunction、その為paramaterを渡すことができる
  ![スクリーンショット 2023-11-01 17.42.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/1779e039-5bf7-18fd-8606-283eeee9d96f.png)

- decoratorはlibraryとして事前用意できる、そして必要な時、classと連動させる
  ![スクリーンショット 2023-11-06 17.30.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/3f3325b4-0fd1-02f6-3271-1b57c35b7630.png)

- decoratorの実行順番は上から下、でもreturn functionの実行順番は下から上
  ![スクリーンショット 2023-11-06 17.37.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/4c61d1a7-0954-9d6e-2eb0-610e97b6f571.png)


##### module namespace
プロジェクト内のコードを分類し、管理する方法
- namespace、"namespace" syntaxでコードをグループ化
- ES6 import/export、"import/export" syntax、ブラウザが支持する
  - 他ファイルに使用したいclassやfunctionやvariable前でexportを追加、使用したいリソースをimportする
  ![スクリーンショット 2023-12-02 10.40.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/f34873f6-f16e-a9ad-f5a7-1fa05e6fd167.png)
  - importしたいファイルの内容をグループ化出来る、`グループ名.class名`の方式で目標classをコール。
    別名前に`as`の追加により、現在ファイル内に適用したい別名をつける。
    * は該当ファイルすべての内容をexport
  ![スクリーンショット 2023-12-02 10.44.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/fd4d084e-5027-5bdb-32b1-0dca79108a00.png)
    - defaultに定義されたcalssをimportの時、直せず別名に命名する
    ![スクリーンショット 2023-12-02 10.57.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/01b35158-5f35-c79b-d52b-b10770e85895.png)
    ![スクリーンショット 2023-12-02 10.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/0087cd03-6ebb-1ce9-1608-db54035e68aa.png)


##### webpack
- ES6 import/exportを使用し、ソースコードをTSファイル分けて、分類した後。
  クライアントがwebpageを開いたとき、サーバーにすべてのJSソースコードを一個ずつrequestする、全体的に時間がかかる
  ![スクリーンショット 2023-12-05 17.14.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/8ff96d53-bcdc-72c3-878a-fa7275e83f2d.png)

- webpack toolを使用し、複数のコードをバンドする
  - https://webpack.js.org/
  ![スクリーンショット 2023-12-05 17.19.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/390edb95-32dd-913f-a315-7b19fa6f6af7.png)


- 以下コマンドでwebpackをインスドール
  `npm install --save-dev webpack webpack-cli webpack-dev-server typescript ts-loader`
- プロジェクトフォルダーの下`webpack.config.js`ファイルを作成。プロジェクトに合わせ、配置コードを入力 
  ```js:例：webpack.config.js
    const path = require('path');

    module.exports = {
      entry: './src/app.ts',
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
      },
      devtool: 'inline-source-map',
      module: {
        rules: [
          {
            test: /\.ts$/,
            use: 'ts-loader',
            exclude: /node_modules/
          }
        ]
      },
      resolve: {
        extensions: ['.ts', '.js']
      }
    };
  ```

- webpackを起動するには、`package.json`にコマンドを定義し、`npm run build（図の例）`コマンドでコンパイルする
  ![スクリーンショット 2023-12-05 18.08.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/7af2d05f-624f-4323-f851-c657b0f4c914.png)

- webpackでソースコードをバンドした結果、一個のファイルにまとめる
  ![スクリーンショット 2023-12-05 18.13.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747384/80d7ae7f-e168-e0c7-aa72-a4b8b0eba465.png)


##### 3rd party libraries
- [lodash](https://lodash.com/) 
  - すべての JavaScriptプロジェクトで使用できる
    - typescriptはこのlibraries内のjsコード直接識別出来ない、そのため[@type/lodash](https://www.npmjs.com/package/@types/lodash)をインスドール`npm install --save @types/lodash` 
      - @type/lodashの中身は`.d.ts`ファイル、このファイルの用途はtypescriptにjsファイルの中身を翻訳すること
  - プロジェクトフォルダーの下`npm i --save lodash`　コマンドでlibrariesを追加

- [class-transformer](https://github.com/typestack/class-transformer) 
  - serverからのjsonデータを、定義済のclassに変換する、便利なツール
  - 例：`const users = plainToClass(UserClass, userJsonData);`、この場合usersはuserJsonDataが含むUserClassインスタンスのlist。

- [class-validator](https://github.com/typestack/class-validator)
  - typescript専用のlibraries