toppy-luna / TodoList-JS

0 stars 0 forks source link

TodoListをTypeScriptで実装する #3

Closed toppy-luna closed 4 years ago

toppy-luna commented 4 years ago

Web系言語の総知識を増やすことが目的で、良く使われていると聞くTypeScriptにJavaScriptのサンプルコードを書き直してみる。

Action

toppy-luna commented 4 years ago

TypeScript環境

インストールコマンド

npm install typescript
npm install ts-node

トランスパイル&実行コマンド

コード

const message: string = "hello world TypeScript!";
console.log(message);

nodeで実行するとJavaScriptではないのでエラーが出る

node helloworld_ts.ts
const message: string = "hello world TypeScript!";
      ^^^^^^^

SyntaxError: Missing initializer in const declaration
:

tscコマンドでJavaScriptにトランスパイルすると.jsファイルが作成される

tsc helloworld_ts.ts
node helloworld_ts.js
hello world TypeScript!

ts-nodeはトランスパイル&実行を一度に行ってくれる便利なモノ

ts-node helloworld_ts.ts
hello world TypeScript!
toppy-luna commented 4 years ago

サンプルコードのトランスパイル結果

エラーが出る。

mv index.js index.ts
ts-node index.ts
index.ts:1:17 - error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`.

1 const express = require('express'); // expressモジュールを読み込む
                  ~~~~~~~
index.ts:2:16 - error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`.

2 const multer = require('multer'); // multerモジュールを読み込む
                 ~~~~~~~
index.ts:3:16 - error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`.

3 const uuidv4 = require('uuid/v4'); // uuidモジュールを読み込む
                 ~~~~~~~
index.ts:53:28 - error TS2339: Property 'findIndex' does not exist on type 'any[]'.

53     const index = todoList.findIndex((item) => item.id === req.params.id);
                              ~~~~~~~~~
index.ts:68:28 - error TS2339: Property 'findIndex' does not exist on type 'any[]'.

68     const index = todoList.findIndex((item) => item.id === req.params.id);
toppy-luna commented 4 years ago

ts-nodeとNode.jsの再インストール

toppy-luna commented 4 years ago

再度トランスパイル

ts-node src/index.ts 
bash: ts-node: command not found
node_modules/.bin/ts-node src/index.ts
(上記エラーなので略)
toppy-luna commented 4 years ago

エラーを解決

エラーメッセージがtype definitionインストールする必要あるのではというのでインストール。@types/xxxというのがtype definitionでnpm installするその他のモジュールを使うときにもそのモジュールの@types/xxxをインストールする必要があるとのこと。

動いた。

npm install @types/node
node_modules/.bin/ts-node src/index.ts 
Listening on port 3000

npxなるnpmに同梱されているモジュールを使うと、node_modules内のローカルモジュールを探して実行してくれるらしい。(伝聞によると、本来npxはインストールせずインスタントモジュール実行する機能を用いるものらしい。テンプレート作成とか。)

npx ts-node src/index.ts
Listening on port 3000

想定外

テストランの(友人とペアプロしていた)とき、arrayにfindIndexがないというエラーで悩まされて、このエラーがここで出る想定だった。このときの解決方法は tsc --initを行ってtsconfig.jsonファイルを作成し、"compilerOptions": {"target": "es2015",を指定した。これはtargetを指定していないときデフォルトでes3(古い)となり、この当時にはarrayにfindIndexがなかったから、とのこと。

@types/nodeをインストールしたことで、arrayのfindIndexが定義されたものと想定する。

tsconfig.jsonがないと静的型付けのメリットであるstrictが行えないみたいなので、ここで行っておく。

npx tsc --init
message TS6071: Successfully created a tsconfig.json file.
toppy-luna commented 4 years ago

VSCode extension Code Runnerをインストール

VSCodeの使い方が未熟だからだと思うんだけど、VSCodeのターミナルでサンプルのようなlistenするコードを実行すると、「Ctrl+C」的なプロセス強制終了ができない。別ターミナルを立ち上げてps kill <PID> としてプロセスを終了させていた。面倒くさい。

想定外。グローバルでts-nodeをインストールする必要があるようだ。理解した上でグローバルインストールしますか。

[Running] ts-node "~/repo/TodoList-JS/src/tempCodeRunnerFile.ts"
/bin/sh: ts-node: command not found

strictが効いてエラーがでるようになっていた・・。

npm install --global ts-node
[Running] ts-node "~/repo/TodoList-JS/src/tempCodeRunnerFile.ts"
src/index.ts(10,7): error TS7034: Variable 'todoList' implicitly has type 'any[]' in some locations where its type cannot be determined.
src/index.ts(14,26): error TS7006: Parameter 'req' implicitly has an 'any' type.
src/index.ts(14,31): error TS7006: Parameter 'res' implicitly has an 'any' type.
src/index.ts(16,14): error TS7005: Variable 'todoList' implicitly has an 'any[]' type.
src/index.ts(21,26): error TS7006: Parameter 'req' implicitly has an 'any' type.
src/index.ts(21,31): error TS7006: Parameter 'res' implicitly has an 'any' type.
src/index.ts(51,33): error TS7006: Parameter 'req' implicitly has an 'any' type.
src/index.ts(51,38): error TS7006: Parameter 'res' implicitly has an 'any' type.
src/index.ts(53,19): error TS7005: Variable 'todoList' implicitly has an 'any[]' type.
src/index.ts(57,25): error TS7005: Variable 'todoList' implicitly has an 'any[]' type.
src/index.ts(66,30): error TS7006: Parameter 'req' implicitly has an 'any' type.
src/index.ts(66,35): error TS7006: Parameter 'res' implicitly has an 'any' type.
src/index.ts(68,19): error TS7005: Variable 'todoList' implicitly has an 'any[]' type.
src/index.ts(72,22): error TS7005: Variable 'todoList' implicitly has an 'any[]' type.

Code RunnerならGUI(もしくはキーショートカット)でプロセスの実行と終了が出来て上記のような煩わしさから解放されるはずだった・・次のコメントでエラーを修正する。ちなみに対象のコードファイルを自動判別して適切なビルダーでビルドしてくれるようだ。

toppy-luna commented 4 years ago

strictのエラーを解決

TS7005は暗黙の型宣言をnoImplicitAnyが有効であることでエラーとなる。strict=trueとすると型チェックパターンすべてでエラーとするようだ。TS7006はモジュールの関数だが型宣言がされていない模様。あ、@types/xxxだ。

npm install @types/typescript
npm install @types/express
npm install @types/multer
npm install @types/uuid

TS7006が消えない。テストランのコードを確認するとrequireではなくimportを使っていた。importに書き換えるとエラーはなくなった。requireは型定義ファイルを読まないのかもしれない(未調査)

修正したコードがこちら

git diff src/index.ts
-const express = require('express'); // expressモジュールを読み込む
-const multer = require('multer'); // multerモジュールを読み込む
-const uuidv4 = require('uuid/v4'); // uuidモジュールを読み込む
+import express from "express";
+import multer from "multer";
+import uuidv4 from "uuid/v4";

-const todoList = [];
+const todoList: any[] = [];
toppy-luna commented 4 years ago

コードをコミットしたのでクローズ