JavaScriptで中規模開発を行うためにTypeScript3（とYarn, DefinitelyTyped, Jest, CircleCI）を導入する

![Screen Shot 2018-08-25 at 22.06.42.png](https://qiita-image-store.s3.amazonaws.com/0/47327/5e40fcaf-1886-2e09-1211-d58d64189f91.png)

# はじめに
TypeScriptはJavaScriptに静的型付けを導入したスーパーセット（上位互換）な言語です。
静的型付けされるのでJavaScriptより大規模な開発に向いています。

僕自身が小規模案件より中規模案件を担当することが増えてきていて、今後ももっと中規模案件を管理するためにTypeScriptの導入を進めています。
新しい言語ということでまだまだ枯れていないTypeScriptなのですが「2018年現在、とりあえずTypeScript書きたいな」という場面のために何をすれば良いかをまとめてみました。

TypeScript本体は2018年8月時点でバージョン3.0.1を使っています。

[次にJSガッツリ書くときはTypeScriptで](https://qiita.com/yuya_presto/items/f625da7b1a4d21c6ce7a)
[Microsoft、JavaScriptのスーパーセット「TypeScript」を発表](http://www.atmarkit.co.jp/news/201210/02/typescript.html)

## 前準備（Gitと.gitignoreとpackages.jsonの準備）

新しい言語や仕組みを使うときはGit化しておくと振り返りが出来るので良いです。

```console
$ git init
Initialized empty Git repository in /Users/yousan/git/ts_ex2/.git/
```

`yarn`を使って`packages.json`も作成しておきます。`-y`オプションを渡すとデフォルトの値で対話を埋めてくれます。

```console
$ yarn init -y
yarn init v0.16.1
warning The yes flag has been set. This will automatically answer yes to all questions which may have security implications.
success Saved package.json
✨  Done in 0.13s.
```

`node_modules`などはGit管理から外したいので`gibo`を使って`.gitignore`を作成します。

```console
$ gibo -u ; gibo Node >> .gitignore
```

`gibo`はNode.jsやPHPといった各種パッケージ用の`.gitignore`を作ってくれるボイラーテンプレートで、「こういうのを省いとくと良いんやで」って教えてくれます。
特に慣れていない言語やパッケージのときには便利です。

[気付いたら.gitignoreはgiboで自動生成する時代になっていた](https://qiita.com/tmknom/items/c4bcebe17d25381fa45d)

実際に作成されるNode.js用のボイラーテンプレートはこんな感じです。

```conf:.gitignore
### https://raw.github.com/github/gitignore/318f8fc99146275e0828737ac2898930c6d8342f/Node.gitignore

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless
```

## インストール

yarnでTypeScript本体と[Node.js標準モジュールの型定義ファイル](https://qiita.com/yousan/items/9668c7ebbc8514d4d9cb#nodejs標準系の型定義ファイル)をインストールします。

```console
$ yarn add typescript @types/node
yarn add v0.16.1
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
^R
success Saved lockfile.
success Saved 1 new dependency
└─ typescript@3.0.1
✨  Done in 1.17s.
```

TypeScript用の設定ファイルを初期化します。

```console
$ yarn tsc -- --init
yarn tsc v0.16.1
$ "/Users/yousan/git/ts_ex2/node_modules/.bin/tsc" --init
message TS6071: Successfully created a tsconfig.json file.
✨  Done in 0.39s.
```

`tsc`はTypeScriptのコンパイラです（tsc:= **T**ype **S**cript **C**ompiler)


`-- --init`と書くとサブコマンドにオプションを渡してくれます。
（`--init`だけだと`yarn`コマンド側のオプションになってしまいます）
余談ですが`yarn tsc`のようにサブコマンドっぽく呼ぶと、`node_modules/.bin/tsc`といったyarn（npm）で入っている実行ファイルを呼び出せます。`npm`の場合だとBashであれば`$(npm bin)/tsc`と書くといい感じに動くんですが、コマンドラインの補完が効きづらいので`yarn`の方が書きやすいですね。

`tsc --init`で作成される`tsconfig.json`です。

```json-doc:tsconfig.json
{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    // "lib": [],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./",                        /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
  }
}
```

これも余談ですが、`tsconfig.json`はコメントありJSONになっています。
[JSON](https://www.json.org)規格だとコメント機能はありませんが、TypeScriptでは[独自にコメント機能を実装](https://github.com/Microsoft/TypeScript/pull/5450/files)しています。

[Allow comments in tsconfig.json ](https://github.com/sarod/TypeScript/commit/b60d88fa80bdd09029610584603734419ef89ae9)

個人的にはJSON自体にコメント機能や[末尾のカンマ（final commas）](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas)を許可して欲しいです。


## TypeScriptを動かしてみる

```typescript:hoge.ts
const main = () => {
    const str: string = 'Hello TypeScript!';
    console.log(str);
}

main()
```

コンパイルしてNode.jsとして実行します。

```bash
$ $(npm bin)/tsc hoge.ts
$ ls
hoge.js       hoge.ts       node_modules  package.json  tsconfig.json yarn.lock

$ node hoge.js
Hello TypeScript!
```

動きました！
`hoge.ts`から`hoge.js`にコンパイルされています。
中身はこんな感じです。

```javascript:hoge.js
var main = function () {
    var str = 'Hello TypeScript!';
    console.log(str);
};
main();
```

## 型ファイルを探す（DefnitlyTypedとTypeSearch）

TypeScriptでnpmなどから提供されているライブラリを使う場合には[型定義ファイル](https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html)が必要です。

多くの型ファイルは「npmのパッケージ名」に`@types/`をつけて`yarn add`します。

例えば[`js-yaml`](https://www.npmjs.com/package/js-yaml)というライブラリを型定義ファイルごと一緒にインストールする場合にはこんな感じです。

```bash
$ yarn add js-yaml @types/js-yaml
yarn add v0.16.1
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency
└─ @types/js-yaml@3.11.2
✨  Done in 0.63s.

```

`@types`で管理されている型定義ファイルは[TypeSearch](https://microsoft.github.io/TypeSearch/)で検索することが出来ます。

![Screen Shot 2018-08-25 at 22.44.11.png](https://qiita-image-store.s3.amazonaws.com/0/47327/e61aef0a-8bde-1680-2163-fb2b12124eae.png)

## TypingsやtsdはDeprecated（非推奨）
過去のTypeScriptバージョン1時代は型定義ファイルのリポジトリ集として[typings](https://www.npmjs.com/package/typings)や[tsd](https://github.com/DefinitelyTyped/tsd)があったのですが、いまは使われていません。

> This package has been deprecated
> Author message:
> Typings is deprecated in favor of NPM @types -- see README for more information

![Screen Shot 2018-08-27 at 0.00.49.png](https://qiita-image-store.s3.amazonaws.com/0/47327/11f98a24-c34e-8b0d-14f1-acfbec393f44.png)

[Deprecate TSD](https://github.com/DefinitelyTyped/tsd/issues/269)

[npmでTypeScriptの型定義を管理できるtypesパッケージについて](https://qiita.com/lacolaco/items/ed1aadf335f12cd3618d)

[TypeScript の型定義ファイルと仲良くなろう](http://developer.hatenastaff.com/entry/2016/06/27/140931)
[TypeScriptの型定義管理ツールTypingsについて](https://qiita.com/literalice/items/d83249a5646abcb0bec6)
[TypeScriptのtsdが非推奨になったので、typingsへ移行](https://qiita.com/ueokande/items/19bb6a22b1285622d2c7)

tsdからTypingsに移行されたのが2016年とのことで、この辺の流れは本当に早いですね。

## Node.js標準系の型定義ファイル
`fs`などのNode.js標準モジュールは`@types/fs`にはありません。

```bash
$ yarn add --dev @types/fs
yarn add v0.16.1
[1/4] 🔍  Resolving packages...
error An unexpected error occured, please open a bug report with the information provided in "/Users/yousan/git/swagger-yaml-to-html/convert/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
```

怒られてしまいますね。
標準形モジュールは`@types/node`を入れておきます。

```bash
$ yarn add @types/node
yarn add v0.16.1
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning Unmet peer dependency "babel-core@^6.0.0 || ^7.0.0-0".
warning Unmet peer dependency "babel-jest@^23.0.0 || ^24.0.0".
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency
└─ @types/node@10.9.2
✨  Done in 6.44s.
```

[typescriptでnodeのfsを動かそうとしてハマったこと](https://www.te-nu.com/entry/2017/12/02/225022)

## TypeScriptの型ファイルが無い場合

`@types`に型定義ファイルがない場合もあります。

```bash
$ npm install --save-dev @types/yaml
npm ERR! code E404
npm ERR! 404 Not Found: @types/yaml@latest

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/yousan/.npm/_logs/2018-08-25T12_46_09_186Z-debug.log
```

自分で型定義ファイル（もどき）を作成することでコンパイルエラーは回避できます。

```typescript:types.d.ts
declare module '*';
```

```typescript:app.ts
import * as hoge from 'yaml';
```

ただし実行時にエラーになってしまう可能性があるので注意が必要です。

[TypeScriptで型定義されていないモジュールを読み込む方法](https://qiita.com/kgtkr/items/2800e44803d9d11af1b8)

## importの仕方

`import * as ... from '...'`です。

```typescript:index.ts
import * as fs from 'fs';

fs.readFileAsync('/path/to/file.txt');
```

[TypeScript 2.7.1 以降での import の書き方](https://qiita.com/karak/items/b7af3cb2843c39fb3949)

# Jestの導入
[Jest](http://jestjs.io)はFacebook社製のテストツールです。
JavaScriptのテストツールといえばchai, Mocha, enzyme, Jasmineといろいろとあったのですが、2018年でモダンでTypeScriptっぽいテストツールは[Jest](https://postd.cc/a-complete-guide-to-testing-javascript-in-2017/)らしいです。

[TypeScriptとJestのチュートリアルはこちら](https://github.com/xogeny/ts-jest-sample
)にきれいにまとまっています。


下記の記事にJestの使い方が網羅されているのでかなり便利です。

[Facebook製のJavaScriptテストツール「Jest」の逆引き使用例](https://qiita.com/chimame/items/e97883fd46b67529d59f)

## Jestのインストール
Yarn（npm）でJestと型定義ファイルをインストールします。

``` bash
$ yarn add --dev typescript jest ts-jest @types/jest
yarn add v0.16.1
[1/4] 🔍  Resolving packages...
warning jest > jest-cli > istanbul-api > istanbul-lib-hook@1.2.1: 1.2.0 should have been a major version bump
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 618 new dependencies.
├─ @babel/code-frame@7.0.0-rc.3
├─ @babel/generator@7.0.0-beta.51
│  └─ jsesc@2.5.1
├─ @babel/helper-function-name@7.0.0-beta.51
├─ @babel/helper-get-function-arity@7.0.0-beta.51
├─ @babel/helper-split-export-declaration@7.0.0-beta.51
...(中略)...
├─ write-file-atomic@2.3.0
├─ ws@5.2.2
├─ xml-name-validator@3.0.0
├─ y18n@3.2.1
├─ yallist@2.1.2
├─ yargs-parser@9.0.2
└─ yargs@11.1.0
✨  Done in 17.27s.
```

Yarn（npm）のサブコマンドの`test`でJestが動くようにしておきます。

```json:packages.json
{
  "devDependencies": {
    "@types/jest": "^23.3.1",
    "jest": "^23.5.0",
    "ts-jest": "^23.1.4",
    "typescript": "^3.0.1"
  },
  "name": "ts_ex2",
  "version": "1.0.0",
  "main": "index.js",
  "author": "Yousan_O <yousan@l2tp.org>",
  "dependencies": {
    "@types/js-yaml": "^3.11.2",
    "js-yaml": "^3.12.0"
  },
  "scripts": {
    "test": "jest"
  }
}
```

この状態でテストが動くことを確認しておきます。

```bash
$ yarn test
yarn test v0.16.1
$ jest
No tests found
In /Users/yousan/git/ts_ex2
  3 files checked.
  testMatch: **/__tests__/**/*.js?(x),**/?(*.)+(spec|test).js?(x) - 0 matches
  testPathIgnorePatterns: /node_modules/ - 3 matches
Pattern:  - 0 matches
error Command failed with exit code 1.
```

テストファイルが無いのでエラーになりましたが、ちゃんと動いていますね♪

## 実際にテストを動かしてみる

```typescript:src/index.ts
export function sampleFunction(x: string): string {
    return x + x;
}
```

```typescript:__tests__/base.spec.ts
import { sampleFunction } from "../src";

describe("This is a simple test", () => {
    test("Check the sampleFunction function", () => {
        expect(sampleFunction("hello")).toEqual("hellohello");
    });
});
```


```bash
$ yarn test
yarn test v0.16.1
$ jest
 PASS  __tests__/base.spec.ts
  This is a simple test
    ✓ Check the sampleFunction function (4ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.347s, estimated 2s
Ran all test suites.
✨  Done in 1.99s.
```

うまくテストが動いていますね！

## Jestでコードカバレッジ（テストの網羅率）を出す

Jestではカバレッジを出力することが出来ます。
下記のように`collectCoverage`を`jest.config.js`に追記します。
（以前は`mapCoverage`も必要だったようですが、現在はDeprecatedになりました。）

```javascript:jest.config.js
module.exports = {
    transform: {
        "^.+\\.tsx?$": "ts-jest",
    },
    testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
    moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
    collectCoverage: true,
};
```

動かしてみます。

```bash
$ yarn jest
yarn jest v0.16.1
$ "/Users/yousan/git/ts_ex2/node_modules/.bin/jest"
 PASS  __tests__/base.spec.ts
  This is a simple test
    ✓ Check the sampleFunction function (8ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.706s
Ran all test suites.
✨  Done in 4.12s.
```

うまく動きましたね！
Qiitaのハイライト（Bashシンタックス）だと赤くなってしまっていますが、カバレッジが高い箇所はグリーンになっていて気分が良いですね😋

<img width="642" alt="Screen Shot 2018-08-28 at 15.35.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/2ca9ef6c-87c1-7ec3-546b-91c21c1641da.png">

# CIで動かす

<img width="1050" alt="Screen Shot 2018-08-28 at 15.40.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/3b312d30-3d48-607c-6f93-095a111d1f8c.png">


中規模開発には欠かせないCIを導入します。
オープンソース（OSS）界隈ではTravisがよく使われているのですが、ここではCircleCIを利用します。
Travisに比べると
「プライベートリポジトリが時間制限付きで無料（慣れるまでには十分な無料枠です）」
「Dockerと相性が良い」
「デプロイやスケジューリングといったWorkFlowという概念が発達している」
「ローカルでCIのテストができる（完璧ではないですが）」
「CIで走ったジョブに対してSSHで接続できる」
っといたメリットがあります。

[CircleCI2.0のWorkflowを試してみる](https://qiita.com/sawadashota/items/ba89382d563bc90bb5cd)
[CircleCI 2.0 をlocalで動かす](https://qiita.com/selmertsx/items/45bd672c2c8ddab1981b)

## CircleCI導入
[CircleCIを開いてGitHubでログインし](https://circleci.com/add-projects/)、左側のメニューから「Add Projects」を選択します。

<img width="1072" alt="Screen Shot 2018-08-28 at 15.41.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/9a5ec293-fac4-c719-a546-844c2607c741.png">

GitHubと連携していればGitHubのリポジトリが見えるので、今回のリポジトリを「SetUp Project」します。

言語は自動判別されていて、今回はそのまま「Node」を選びます。

<img width="1074" alt="Screen Shot 2018-08-28 at 15.42.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/7c245854-1b50-b27b-a8bb-b79bc7c7977c.png">

画面中央部分にある`Populate the config.yml with the contents of the sample .yml (shown below).`の「Copy To Clipboard」でサンプルのconfig.ymlをコピーします。

これをリポジトリに作成し貼り付けます。

```bash
$ mkdir .circleci
$ cat > .circleci/config.yml
```

```yaml:.circleci/config.yml
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/node:7.10
      
      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/mongo:3.4.4

    working_directory: ~/repo

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "package.json" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-

      - run: yarn install

      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}
        
      # run tests!
      - run: yarn test
```

完了したらGitでコミットプッシュします。

```bash
ga -m 'for circle'
[master e22e2b0] for circle
 2 files changed, 38 insertions(+)
 create mode 100644 .circleci/config.yml
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 859 bytes | 859.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:yousan/ts_ex2.git
   51b7562..e22e2b0  master -> master
```

`ga -m`は`git add...`の省略形です。
[git add --all; git commit -m 'first commit'; git push --all を省略化する]()

先ほどのブラウザの画面から「Start Building」をクリックして初回のビルドを走らせます。

うまくいくと…　オールグリーンでテスト完了です！

<img width="1075" alt="Screen Shot 2018-08-28 at 15.47.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/282c1094-a46b-e4ea-45f4-77ef4264d9d1.png">


気分が良いですね😋

## GitHubとの連携

GitHubの方でもテストにパスをしたグリーンのチェックマークが付きます。

<img width="536" alt="Screen Shot 2018-08-28 at 15.49.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/71820033-5c56-9460-3d5b-ed521f233358.png">


CircleCIではテストだけではなくビルド、デプロイなどいろいろなことが出来ます。
まずはテストを自動で通しておくようにすれば中規模開発で非常に役立ちます。
僕が管理しているチーム開発では、機能を開発する際にブランチを切り、マージの際にプルリクエストで投げてもらうようにしています。
そうすることでCIとプルリクマージを組み合わせることでテストをパスすることが保証されるので、コードの品質が保たれます。
もちろんですがちゃんとした開発の場合にはテストのカバレッジや品質も重要です。テストを自動化することで次のステップに注力することが出来ます。
この仕組は中規模を意識した開発では最低限の品質保証としてとても強力です。

# コーディング規約に準拠する
中規模案件を回す際、コーディング規約を定めると良いです。
特に複数人がコードの同じ箇所をメンテナンスする場合にはコーディング規約があったほうが良いです。逆にコーディング規約が無いとどんどん崩壊していきます。

## Standard

<img width="972" alt="Screen Shot 2018-08-28 at 18.49.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/a7f8825d-119f-3a22-0e30-8e4dc405e5bf.png">


最近注目のJSLintツール、[Standard](https://standardjs.com)（Standard JS）です。

TypeScript用に`standard typescript-eslint-parser eslint-plugin-typescript`をインストールします。

```
$ yarn add standard typescript-eslint-parser eslint-plugin-typescript --dev
yarn add v0.16.1
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning Unmet peer dependency "babel-core@^6.0.0 || ^7.0.0-0".
warning Unmet peer dependency "babel-jest@^23.0.0 || ^24.0.0".
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 118 new dependencies.
├─ acorn-jsx@3.0.1
...
```

動かす場合にはオプションをつけて`standard`コマンドを呼び出します。

```bash
$ yarn standard standard -- --parser typescript-eslint-parser --plugin typescript *.ts
yarn standard v0.16.1
$ "/Users/yousan/git/ts_ex2/node_modules/.bin/standard" standard --parser typescript-eslint-parser --plugin typescript hoge.ts
standard: Use JavaScript Standard Style (https://standardjs.com)
standard: Run `standard --fix` to automatically fix some problems.
  /Users/yousan/git/ts_ex2/hoge.ts:2:1: Expected indentation of 2 spaces but found 6.
  /Users/yousan/git/ts_ex2/hoge.ts:3:1: Expected indentation of 2 spaces but found 6.
error Command failed with exit code 1.
```

この例では「スペースは6じゃなくて2を使ってね！」というエラーで怒られました。

`--fix`オプションをつけると自動で修正してくれます。

```bash
yarn standard standard -- --parser typescript-eslint-parser --plugin typescript *.ts --fix
yarn standard v0.16.1
$ "/Users/yousan/git/ts_ex2/node_modules/.bin/standard" standard --parser typescript-eslint-parser --plugin typescript hoge.ts --fix
✨  Done in 1.75s.
```

```diff:hoge.ts
diff --git a/hoge.ts b/hoge.ts
index 0836004..b052802 100644
--- a/hoge.ts
+++ b/hoge.ts
@@ -1,6 +1,6 @@
 const main = () => {
-      const str: string = 'Hello TypeScript!';
-      console.log(str);
+  const str: string = 'Hello TypeScript!'
+  console.log(str)
 }

 main()
```

Standardは**めっちゃお手軽にコーディング規約を導入**できることが強みです。

ただセミコロン無しというのは…、賛否が分かれるところですね。

## デフォルトオプションの設定
`packages.json`の`standard`の項目にTypeScript用のデフォルトオプションを指定できます。

```json:packages.json
  "standard": {
    "parser": "typescript-eslint-parser",
    "plugins": [ "typescript" ]
  }
```

これで気軽に呼べます。


```bash
$ yarn standard standard -- *.ts --fix
yarn standard v0.16.1
$ "/Users/yousan/git/ts_ex2/node_modules/.bin/standard" standard hoge.ts --fix
✨  Done in 1.75s.
```

# ブラウザで動かすwebpack

![Screen Shot 2018-08-25 at 22.05.47.png](https://qiita-image-store.s3.amazonaws.com/0/47327/eb496038-7e29-a7d5-1e41-4866545a6d74.png)

https://webpack.js.org

## Babelのインストール

![Screen Shot 2018-08-25 at 22.07.02.png](https://qiita-image-store.s3.amazonaws.com/0/47327/508d13a0-b1a7-fd8d-db98-4508e1167be6.png)

https://qiita.com/karak/items/29ff148788f5abb15331

```bash
$ yarn add babel

yarn add v0.16.1
[1/4] 🔍  Resolving packages...
warning babel@6.23.0: In 6.x, the babel package has been deprecated in favor of babel-cli. Check https://opencollective.com/babel to support the Babel maintainers
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency
└─ babel@6.23.0

✨  Done in 0.50s.

```

# 謝辞
今回のTypeScriptを導入するにあたって @naname さん、 @kurouw さんに色々と教えてもらいました。
TypeScriptが流行していること、その理由、中規模に向いていること、TypeScriptの書き方、コーディング規約、テストの重要性。大切なことを教えてもらいました。重ねてありがとうございます！