Node.jsで実行できるスクリプトをTypescriptで作る【備忘】

# Node.jsで実行できるスクリプトをTypescriptで作る【備忘】

`Typescript`はまだまだ初心者ですが備忘録として残しておこうかと思った次第。

## ● 完成系のイメージ

チームメンバーのスキル的に`npm`でインストールは無い方が無難かなと思いまして、<br>`node`でjsファイルを指定して実行する方針にしました。
なので `bin`ではなく `main`で 出力先の`./dist/index.js`としています。
※ 実際のスキル感次第で変更してもいいかなと思ってます。

```bash:実行時
$ node cli-tool opt1

// 実行結果
-> Hello, opt1!
```

```bash:TS→JS
# package.jsonのbuildを実行
$ yarn build
```

```bash:自機の実行環境
# macOS
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H2

# node.js
$ node -v
v14.7.0

# yarn
$ yarn --version
1.22.5
```
## ● 開発環境

### ディレクトリ

```txt:ディレクトリ構成
cli-tool
  ├── dist/
  │   └── index.js
  ├── node_modules/
  ├── src/
  │   ├── main.ts
  │   └── component.ts # いい感じにファイルを分割する
  ├── package.json
  ├── tsconfig.json
  └── yarn.lock
```

### コンフィグ

```bash:
# 作業ディレクトリ確認
$ pwd 
// -> cli-tool/

# モジュールインストール
$ yarn add --dev @vercel/ncc typescript

# tsconfig作成
$ ./node_modules/.bin/tsc --init
```

型定義なんかも入れて、package.jsonはこんな感じです。

```json:package.json
{
  "name": "cli-tool",
  "version": "1.0.0",
  "license": "UNLICENSED",
  "main": "./dist/index.js",
  "scripts": {
    "build": "ncc build src/main.ts --minify",
    "watch": "ncc build src/main.ts --watch",
  },
  "dependencies": {
    "cli-color": "^2.0.0",
    "command-line-args": "^5.1.1",
    "command-line-usage": "^6.1.0",
    "source-map-support": "^0.5.19"
  },
  "devDependencies": {
    "@types/cli-color": "^2.0.0",
    "@types/command-line-args": "^5.0.0",
    "@types/command-line-usage": "^5.0.1",
    "@types/node": "^14.14.5",
    "@types/source-map-support": "^0.5.3",
    "@vercel/ncc": "^0.24.1",
    "typescript": "^4.0.5"
  }
}

```




tsconfig.jsonは参考記事から変わらず

```json:tsconfig.json
{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Basic Options */

    "target": "ES2018",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "declaration": false,                   /* Generates corresponding '.d.ts' file. */
    "declarationMap": false,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    "outDir": "./dist",                        /* Redirect output structure to the directory. */
outDir. */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */

    /* 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 */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */

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

    /* Advanced Options */
    "skipLibCheck": true,                     /* Skip type checking of declaration files. */
    "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
  },
  "include": ["src/**/*"]
}

```

```ts:main.ts
#!/usr/bin/env node
"use strict";

// ------------
// メイン処理
// ------------

const optionArg = { argv: process.argv };

const test = () => {
    const argv = optionArg.argv;
    const name = argv[2];
    if (name) {
        console.log(`Hello, ${name}!`);
    } else {
        console.log(`alert:require argv.`);
    }
};

const main = () => {
    test();
};

if (require.main === module) {
    main();
}
```

## ● 参考記事

- https://shibukawa.gitlab.io/quicktypescript/clienv.html
- https://future-architect.github.io/typescript-guide/clienv.html#
- https://future-architect.github.io/articles/20200319/