かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

React JS のプロジェクトを TypeScript 化したメモ

環境づくりの勉強がてら ReactHooks・テストは JEST + Enzyme で作っていたプロジェクトを TypeScript 化したメモ

1. TypeScript 化のパッケージをインストール して babel 関連のパッケージをアンインストール

TypeScript 化するにあたって必要なパッケージをインストールする

$ yarn add -D typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser

React まわりの types をインストール

$ yarn add -D @types/react @types/react-dom @types/node

tscコンパイルするので babel は不要になる

$ yarn remove @babel/core @babel/preset-env @babel/preset-react

.babel.comfig.js も削除

2. 設定ファイルの作成

tsconfig.json

下記コマンドで設定ファイルを生成

$ tsc --init

tsconfig.json ができるので編集

{
  "compilerOptions": {
    "lib": ["dom", "ES2017"],
    "allowJs": true,
    "jsx": "react",
    "declaration": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "tests"]
}

段階的に TypeScript 化しようと思ったので、"allowJs": true, を設定しました。

.eslintrc.json

babel の設定で作成していた .eslintrc.json を編集します

 {
+  "parser": "@typescript-eslint/parser",
   "extends": [
-    "eslint:recommended",
+    "plugin:@typescript-eslint/recommended",
+    "prettier/@typescript-eslint",
     "plugin:prettier/recommended",
     "plugin:react/recommended"
   ],
-  "env": {
-    "browser": true,
-    "node": true
-  },
   "parserOptions": {
     "ecmaVersion": 2018,
     "sourceType": "module",
-    "ecmaFeatures": {
-      "jsx": true
-    }
   },
   "plugins": ["react-hooks"],
   "rules": {
+    "no-console": ["warn", { "allow": ["warn", "error"] }],
     "react-hooks/rules-of-hooks": "error",
     "react-hooks/exhaustive-deps": "error",
-    "space-before-function-paren": ["error", "never"],
+    "space-before-function-paren": 0,
+    "@typescript-eslint/indent": 0,
+    "@typescript-eslint/no-explicit-any": 0,
     "semi": ["error", "always"],
     "object-shorthand": ["error", "always", { "avoidQuotes": true }]
   }
}

function method<T extends (…arg: any) => any>() {…} という書き方でどうやっても Unexpected space before function parentheses になってしまったの space-before-function-paren のルールは無効にしました。

3. build コマンドの作成

cjs, esm 両パターンでコンパイルします。
package.json に build コマンドとそれぞれのエントリーポイントの指定作成します

package.json

{
  "main": "dist-cjs/index.js",
  "module": "dist-esm/index.js",
  "types": "dist-cjs/index.d.ts",
  …
  "scripts": {
    "build:cjs": "tsc --project . --module commonjs --outDir ./dist-cjs",
    "build:esm": "tsc --project . --module esNext --outDir ./dist-esm",
    …
  },
}

build されたファイルは git 管理したくないので .gitignore に出力されるディレクトリを追加します

.gitignore

/dist-cjs
/dist-esm

一度にコンパイルできるようにする

yarn build コマンドで一度に両方 build したいので複数の npm script を実行できる npm-run-all を使って実現します

npm-run-al をインストール

$ yarn add -D npm-run-all

package.json にコマンドを追加

{
  "scripts": {
    "build": "npm-run-all -s build:cjs build:esm",
    …
  }
}

ここまでで、React のファイルを TypeScript で扱うことができるようになりました。

4. Test も TypeScript 化する

続いて JEST + Enzyme で行っていたテストも TypeScript 対応にしていきます。
必要なパッケージのインストール

$ yarn add -D ts-jest @types/jest @types/enzyme @types/enzyme-adapter-react-16

Jest用のTypeScriptプリプロセッサ(ts-jest)をインストールします。これにより、Jestはその場でTypeScriptをトランスパイルすることができ、source-mapをサポートします
cf. Jest - TypeScript Deep Dive 日本語版

Jest の設定 ( jest.config.js )

テストを ts-jest で変換するように設定し、対象ファイルに .ts, .tsx を含めるように変更します。

jest.config.js

module.exports = {
  // An array of file extensions your modules use
  moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
  // A map from regular expressions to paths to transformers
  transform: {
    "^.+.(js|jsx|ts|tsx)$": "ts-jest"
  },
  // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
  transformIgnorePatterns: [
    "/node_modules/.+.(js|jsx)$",
  ],
}

enzyme の設定ファイルを typescript に変更する

enzyme-adapter-react-16Adapter を設定していたファイルの拡張子を .js から .ts に変更

- __tests__/setup.enzyme.js
+__tests__/setup.enzyme.ts 

テスト実行時に自動的に読み込むファイルを .ts のものに変更します。
jest.config.js

module.exports = {
   // A list of paths to modules that run some code to configure or set up the testing framework before each test
-  setupFilesAfterEnv: ['<rootDir>/__tests__/setup.enzyme.js'],
+  setupFilesAfterEnv: ['<rootDir>/__tests__/setup.enzyme.ts'],
}

 
これで、テストも TypeScript で動作するように出来ました!
作業したログを元にしたメモなので参考程度に…
ちゃんと理解するにはそれぞれの設定とかのドキュメントをしっかり読む必要がありそうです。(英語力…)


[参考]

Git タグのいろいろメモ

TAG の作成

$ git tag -a <tag_name>
# コメント付きで作成
$ git tag -a <tag_name> -m 'comment'

TAG の確認

$ git tag

TAG をリモートに push する

$ git push origin <tag_name>
# 一度にpush
$ git push origin --tags

TAG の削除

$ git tag -d <tag_name>
# リモートのタグを削除
$ git push origin :<tag_name>
# 又は
$ git push --delete origin <tag_name> 

GUI で触ってるとすぐ忘れる…


[参考]

GitHub リポジトリ名を変えた時にすること

パッケージ名が被ってて使えなかったとか、名前がイケてないとか、GitHubリポジトリ名を変えたいことが時々あります。
リポジトリ名の変更自体は GitHub のサイト上からカンタンにできるのですが、変更すると local のパスが変わってしまうので、パスを合わせる必要があります。

リモートのリポジトリを変更する

リポジトリの確認

$ git remote -v

リモートのリポジトリを変更

$ git remote set-url origin <new URL>

これで再度 git remote -v して表示されるリポジトリのURLが合っていればOK。

fork してる元を変更する場合

自分のリポジトリならリモートリポジトリは origin git@--- で登録されていると思いますが、Fork 元のリポジトリの場合は自分で追加する必要があり、Fork元が変更になっている場合は、先のコマンドの origin の部分を自身で登録したものに変更すればOKです。

e.g.

$ git remote -v
origin  git@github.com:my-name/homepage.git (fetch)
origin  git@github.com:my-name/homepage.git (push)
upstream    git@github.com:forked-username/homepage.git (fetch)
upstream    git@github.com:forked-username/homepage.git (push)

この場合ローカルでは fork 元を upstream で登録しているので、Fork 元のリポジトリのURLを変更する場合は次のような感じ。

$ git remote set-url upstream <new URL>

 
GitHub のヘルプを見れば解決でした。


[参考]