LoginSignup
5
4

More than 5 years have passed since last update.

TypeScriptでReact

Last updated at Posted at 2019-03-23

概要

ReactをTypeScriptでやってみます。
まずは、情報収集など。

環境

$ yarn --version
1.15.2
$ create-react-app --version
2.1.8

三行まとめ

  • React + TypeScriptについて調べた
  • TypeScript有無のプロジェクトを比較した
  • SFC?FC?

情報収集

ググって収集できた情報源。
意外とヒットしなかった印象。
まだあまり使われていない組み合わせ?

https://facebook.github.io/create-react-app/docs/adding-typescript
https://www.typescriptlang.org/docs/handbook/react-&-webpack.html
https://www.typescriptlang.org/docs/handbook/jsx.html
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
https://qiita.com/alfas/items/539ade65926deb530e0e
https://typescript-jp.gitbook.io/deep-dive/tsx/react
https://github.com/Microsoft/TypeScript-React-Starter#typescript-react-starter
https://qiita.com/namaozi/items/7446804126a055caf254
https://www.dkrk-blog.net/javascript/react_ts03

プロジェクト作成

create-react-app--typescript有無のプロジェクトを作成し、比較する。
node_modulesは比較から除外。

$ create-react-app tsx-react-app # typescript無し
$ tree -I node_modules ./jsx-react-app/
./jsx-react-app/
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── serviceWorker.js
└── yarn.lock

2 directories, 13 files

$ create-react-app tsx-react-app --typescript # typescript有り
$ tree -I node_modules ./tsx-react-app/
./tsx-react-app/
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── react-app-env.d.ts
│   └── serviceWorker.ts
├── tsconfig.json
└── yarn.lock

2 directories, 15 files

プロジェクト比較

$ diff --new-file --unified ./jsx-react-app/ ./tsx-react-app/
共通のサブディレクトリー: ./jsx-react-app/.git と ./tsx-react-app/.git
diff --new-file --unified ./jsx-react-app/README.md ./tsx-react-app/README.md
--- ./jsx-react-app/README.md   2019-03-23 20:42:45.877562453 +0900
+++ ./tsx-react-app/README.md   2019-03-23 20:41:53.565223301 +0900
@@ -42,27 +42,3 @@
 You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

 To learn React, check out the [React documentation](https://reactjs.org/).
-
-### Code Splitting
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
-
-### Analyzing the Bundle Size
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
-
-### Making a Progressive Web App
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
-
-### Advanced Configuration
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
-
-### Deployment
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
-
-### `npm run build` fails to minify
-
-This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
共通のサブディレクトリー: ./jsx-react-app/node_modules と ./tsx-react-app/node_modules
diff --new-file --unified ./jsx-react-app/package.json ./tsx-react-app/package.json
--- ./jsx-react-app/package.json    2019-03-23 20:42:45.877562453 +0900
+++ ./tsx-react-app/package.json    2019-03-23 20:41:53.561223273 +0900
@@ -1,11 +1,16 @@
 {
-  "name": "jsx-react-app",
+  "name": "tsx-react-app",
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "@types/jest": "24.0.11",
+    "@types/node": "11.11.6",
+    "@types/react": "16.8.8",
+    "@types/react-dom": "16.8.3",
     "react": "^16.8.5",
     "react-dom": "^16.8.5",
-    "react-scripts": "2.1.8"
+    "react-scripts": "2.1.8",
+    "typescript": "3.3.4000"
   },
   "scripts": {
     "start": "react-scripts start",
共通のサブディレクトリー: ./jsx-react-app/public と ./tsx-react-app/public
共通のサブディレクトリー: ./jsx-react-app/src と ./tsx-react-app/src
diff --new-file --unified ./jsx-react-app/tsconfig.json ./tsx-react-app/tsconfig.json
--- ./jsx-react-app/tsconfig.json   1970-01-01 09:00:00.000000000 +0900
+++ ./tsx-react-app/tsconfig.json   2019-03-23 20:41:53.833225155 +0900
@@ -0,0 +1,25 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "lib": [
+      "dom",
+      "dom.iterable",
+      "esnext"
+    ],
+    "allowJs": true,
+    "skipLibCheck": true,
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "strict": true,
+    "forceConsistentCasingInFileNames": true,
+    "module": "esnext",
+    "moduleResolution": "node",
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": true,
+    "jsx": "preserve"
+  },
+  "include": [
+    "src"
+  ]
+}
diff --new-file --unified ./jsx-react-app/yarn.lock ./tsx-react-app/yarn.lock
--- ./jsx-react-app/yarn.lock   2019-03-23 20:42:43.465547689 +0900
+++ ./tsx-react-app/yarn.lock   2019-03-23 20:41:52.557216320 +0900
@@ -970,16 +970,53 @@
     "@svgr/plugin-svgo" "^4.0.3"
     loader-utils "^1.1.0"

+"@types/jest-diff@*":
+  version "20.0.1"
+  resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89"
+  integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==
+
+"@types/jest@24.0.11":
+  version "24.0.11"
+  resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.11.tgz#1f099bea332c228ea6505a88159bfa86a5858340"
+  integrity sha512-2kLuPC5FDnWIDvaJBzsGTBQaBbnDweznicvK7UGYzlIJP4RJR2a4A/ByLUXEyEgag6jz8eHdlWExGDtH3EYUXQ==
+  dependencies:
+    "@types/jest-diff" "*"
+
 "@types/node@*":
   version "11.10.5"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-11.10.5.tgz#fbaca34086bdc118011e1f05c47688d432f2d571"
   integrity sha512-DuIRlQbX4K+d5I+GMnv+UfnGh+ist0RdlvOp+JZ7ePJ6KQONCFQv/gKYSU1ZzbVdFSUCKZOltjmpFAGGv5MdYA==

+"@types/node@11.11.6":
+  version "11.11.6"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
+  integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
+
+"@types/prop-types@*":
+  version "15.7.0"
+  resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.0.tgz#4c48fed958d6dcf9487195a0ef6456d5f6e0163a"
+  integrity sha512-eItQyV43bj4rR3JPV0Skpl1SncRCdziTEK9/v8VwXmV6d/qOUO8/EuWeHBbCZcsfSHfzI5UyMJLCSXtxxznyZg==
+
 "@types/q@^1.5.1":
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18"
   integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==

+"@types/react-dom@16.8.3":
+  version "16.8.3"
+  resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.3.tgz#6131b7b6158bc7ed1925a3374b88b7c00481f0cb"
+  integrity sha512-HF5hD5YR3z9Mn6kXcW1VKe4AQ04ZlZj1EdLBae61hzQ3eEWWxMgNLUbIxeZp40BnSxqY1eAYLsH9QopQcxzScA==
+  dependencies:
+    "@types/react" "*"
+
+"@types/react@*", "@types/react@16.8.8":
+  version "16.8.8"
+  resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.8.tgz#4b60a469fd2469f7aa6eaa0f8cfbc51f6d76e662"
+  integrity sha512-xwEvyet96u7WnB96kqY0yY7qxx/pEpU51QeACkKFtrgjjXITQn0oO1iwPEraXVgh10ZFPix7gs1R4OJXF7P5sg==
+  dependencies:
+    "@types/prop-types" "*"
+    csstype "^2.2.0"
+
 "@types/tapable@1.0.2":
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.2.tgz#e13182e1b69871a422d7863e11a4a6f5b814a4bd"
@@ -2858,6 +2895,11 @@
   dependencies:
     cssom "0.3.x"

+csstype@^2.2.0:
+  version "2.6.3"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.3.tgz#b701e5968245bf9b08d54ac83d00b624e622a9fa"
+  integrity sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg==
+
 cyclist@~0.2.2:
   version "0.2.2"
   resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
@@ -9355,6 +9397,11 @@
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

+typescript@3.3.4000:
+  version "3.3.4000"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.4000.tgz#76b0f89cfdbf97827e1112d64f283f1151d6adf0"
+  integrity sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==
+
 uglify-js@3.4.x, uglify-js@^3.1.4:
   version "3.4.9"
   resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"

プロジェクトの主な違い

  • tsxでは、READMEの後半部が削除されている
  • tsxでは、package.jsonyarn.lockに、typescript関連が追加されている
  • tsxでは、tsconfig.jsonが新規追加されている

publicフォルダ比較

$ diff --report-identical-files ./jsx-react-app/public/ ./tsx-react-app/public/
ファイル ./jsx-react-app/public/favicon.ico と ./tsx-react-app/public/favicon.ico は同一です
ファイル ./jsx-react-app/public/index.html と ./tsx-react-app/public/index.html は同一です
ファイル ./jsx-react-app/public/manifest.json と ./tsx-react-app/public/manifest.json は同一です

srcフォルダ比較

$ diff --brief --report-identical-files ./jsx-react-app/src/ ./tsx-react-app/src/
ファイル ./jsx-react-app/src/App.css と ./tsx-react-app/src/App.css は同一です
./jsx-react-app/src/ のみに存在: App.js
./jsx-react-app/src/ のみに存在: App.test.js
./tsx-react-app/src/ のみに存在: App.test.tsx
./tsx-react-app/src/ のみに存在: App.tsx
ファイル ./jsx-react-app/src/index.css と ./tsx-react-app/src/index.css は異なります
./jsx-react-app/src/ のみに存在: index.js
./tsx-react-app/src/ のみに存在: index.tsx
ファイル ./jsx-react-app/src/logo.svg と ./tsx-react-app/src/logo.svg は同一です
./tsx-react-app/src/ のみに存在: react-app-env.d.ts
./jsx-react-app/src/ のみに存在: serviceWorker.js
./tsx-react-app/src/ のみに存在: serviceWorker.ts

.jsファイルと.tsxファイル比較

App.jsとApp.tsx
$ diff --unified --report-identical-files ./jsx-react-app/src/App.js ./tsx-react-app/src/App.tsx
--- ./jsx-react-app/src/App.js  2019-03-23 20:42:45.877562453 +0900
+++ ./tsx-react-app/src/App.tsx 2019-03-23 20:41:53.565223301 +0900
@@ -9,7 +9,7 @@
         <header className="App-header">
           <img src={logo} className="App-logo" alt="logo" />
           <p>
-            Edit <code>src/App.js</code> and save to reload.
+            Edit <code>src/App.tsx</code> and save to reload.
           </p>
           <a
             className="App-link"
App.test.jsとApp.test.tsx
$ diff --unified --report-identical-files ./jsx-react-app/src/App.test.js ./tsx-react-app/src/App.test.tsx
ファイル ./jsx-react-app/src/App.test.js と ./tsx-react-app/src/App.test.tsx は同一です
index.jsとindex.tsx
$ diff --unified --report-identical-files ./jsx-react-app/src/index.js ./tsx-react-app/src/index.tsx
ファイル ./jsx-react-app/src/index.js と ./tsx-react-app/src/index.tsx は同一です
serviceWorker.jsとserviceWorker.ts
$ diff --unified --report-identical-files ./jsx-react-app/src/serviceWorker.js ./tsx-react-app/src/serviceWorker.ts
--- ./jsx-react-app/src/serviceWorker.js    2019-03-23 20:42:45.877562453 +0900
+++ ./tsx-react-app/src/serviceWorker.ts    2019-03-23 20:41:53.565223301 +0900
@@ -20,10 +20,18 @@
     )
 );

-export function register(config) {
+type Config = {
+  onSuccess?: (registration: ServiceWorkerRegistration) => void;
+  onUpdate?: (registration: ServiceWorkerRegistration) => void;
+};
+
+export function register(config?: Config) {
   if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
     // The URL constructor is available in all browsers that support SW.
-    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
+    const publicUrl = new URL(
+      (process as { env: { [key: string]: string } }).env.PUBLIC_URL,
+      window.location.href
+    );
     if (publicUrl.origin !== window.location.origin) {
       // Our service worker won't work if PUBLIC_URL is on a different origin
       // from what our page is served on. This might happen if a CDN is used to
@@ -54,7 +62,7 @@
   }
 }

-function registerValidSW(swUrl, config) {
+function registerValidSW(swUrl: string, config?: Config) {
   navigator.serviceWorker
     .register(swUrl)
     .then(registration => {
@@ -98,7 +106,7 @@
     });
 }

-function checkValidServiceWorker(swUrl, config) {
+function checkValidServiceWorker(swUrl: string, config?: Config) {
   // Check if the service worker can be found. If it can't reload the page.
   fetch(swUrl)
     .then(response => {

また、react-app-env.d.tsはtsxのみ

react-app-env.d.ts
/// <reference types="react-scripts" />

感想

  • React + TypeScriptは、まだまだこれから?
  • Stateless Functional Component(SFC)はなくなった?
  • Function Components(FC)ができた?
  • 何か作って理解を深めよう
  • TypeScriptを使いたいならAngular?
  • tsconfig.jsonとは?
  • react-app-env.d.tsとは?

以上

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4