開発案件で使われることも多いTypeScriptの基礎について扱っていきます。今回は、TypeScriptで、下の「Hit&Blowゲーム(数字当て処理の実装)」サンプルを作成していきたいと思います。
機能概要書を参考にHit&Blowゲームを制作していきますが、その前に準備段階として
・TypeScriptでの環境構築
・機能概要書の読み込み
を確認していきましょう。
TypeScriptとは?
TypeScriptは、安全なコードが書ける/エディタの補完機能を利用できる/導入コストが低いなどの利点から人気を集めているプログラミング言語の1つです。
TypeScriptは、そのままではブラウザやNode.js では実行できません。その為、TypeScriptのコンパイラを使って、JavaScriptに変換する必要があります。
まずは、Playground環境で、TypeScriptのソースコードを記述して、コンパイルされることを確認してみましょう。
では開発を進めていくうえで、TypeScriptを導入するには、どのようにすれば良いのでしょうか?
「npm」パッケージをインストールすることで、TypeScriptをJavaScriptにコンパイルする機能を持った「tsc」コマンドを使って、拡張子が「.ts」のファイルを「.js」ファイルに変換します。
より詳しくみていきましょう。
TypeScriptでの環境構築
端末にNode.jsをインストール後、TypeScriptをインストールします。
VSCodeのターミナルを開いて次のコマンドを入力します。
$ npm install -D typescript@4.3.5
npmパッケージをインストールすることで、TypeScriptをJavaScriptにコンパイルする機能を持った「tsc」コマンドを使用することができます。(ここでは、動作保障の為に、@4.3.5と指定しています)
では早速、「tsc」コマンドを使ってみましょう!
作業環境の準備
まずは、TypeScriptでアプリケーションを開発するための環境を構築していきましょう。
・「package.json」の用意
Node.jsのプロジェクトはnpmパッケージ1個に対応します。すなわち、プロジェクトを1つ開発するということは、パッケージを1つ作り上げることを意味します。
npmにとってパッケージというのは、package.jsonというファイルの親ディレクトリに含まれるファイル群のことです。
ターミナルを開き、任意のディレクトリで次のコマンドを実行します。
$ mkdir node-app $ cd node-app $ npm init -y
これで、node-appディレクトリにpackage.json が追加された状態になりました。
package.json にscriptsのブロックを追加し、ソースをコンパイルする為のnpm scriptsを定義します。
{ “scripts”: { - “test”: “echo\ ”Error: no test specified\”&& exit 1 ” + “build”: “tsc”, + “dev”: “tsc -w”, + “start”: “node dist/index.js” }
先ほど、tscを使ったコンパイルを実際に実行してみましたが、tsconfig.json上でコンパイルの設定を行うこともできます。では実際に、tsconfig.jsonを作成していくつかのオプションを確認してみましょう。
例えば、次のような設定ができます
・コンパイル対象、または対象外にするファイル ⇒ exclude / include
・コンパイル後の出力ディレクトリや出力ファイル ⇒ outDir / rootDir
・出力するECMAScriptのバージョン/型チェックの強度/構文チェック
次のコマンドを実行してください。
$ tsc --init
生成されたtsconfig.json ファイルの内容を変更します。
{ "compilerOptions": { “outDir”: “./dist”, “rootDir”: “./src”, "target": "es5", "module": "commonjs", "strict": true, } }
・「.ts」ファイルのコンパイル
実際にコードを記述するTypeScriptファイルを作成しましょう。
(srcディレクトリを作成し、index.ts ファイルを追加します)
$ mkdir src $ touch src/index.ts
・src/ index.ts
const sayHello = (name: string) => { return `Hello, ${name}! ` } console.log(sayHello(‘Tanaka Tarou’) )
この状態で、$npm run buildを実行してみてください。distフォルダにindex.jsが出力されたでしょうか。それでは、 $npm run startを実行してみましょう。ターミナル上に「Hello, Tanaka Tarou!」と表示されれば成功です。
ここで、src/index.tsファイルのconsole.logの部分をprocess.stdout.writeに変更してみます。
const sayHello = (name: string) => { return `Hello, ${name}! ` } - console.log(sayHello(‘Tanaka Tarou’) ) + process.stdout.write(sayHello(‘Tanaka Tarou’) )
エラーが発生していると思うので、Node.jsの型定義ファイルを、npm上にあるものをインストールする形で、以下のコマンドを入力します。
$ npm install -D @types/node@16.4.13
では、実際にHit&Blowゲームの処理を書いていきましょう!
画面設計書の読み込み
添付資料の「機能概要書(Hit&Blowサンプル).xlsx」を確認してください。
・src/index.ts
class HitAndBlow { private readonly answerSouce = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] answer: Array<string> = []; tryCount = 0; setting(): void { // 処理を記載 } async play(): Promise<void>{ // 処理を記載 } private check(input: string[]): {hit: number; blow: number}{ let hitCount = 0 let blowCount = 0 // 処理を記載 return { hit: hitCount, blow: blowCount, } } end() { printLine(`正解です!\n 試行回数: ${this.tryCount}回`) process.exit() } } const printLine = (text:string, breakLine:boolean=true) => { process.stdout.write(text + (breakLine ? '\n': '')) } const promptInput = async (text: string) => { printLine(`\n${text}\n`, false) const input: string = await new Promise((resolve) => process.stdin.once('data', (data) => resolve(data.toString())) ) return input.trim() } ;(async() => { const hitAndBlow = new HitAndBlow() await hitAndBlow.setting() await hitAndBlow.play() hitAndBlow.end() })()
HitAndBlowクラスのそれぞれのメソッドに中身を追記していきましょう。
setting(): void { const answerLength = 3; while (this.answer.length < answerLength){ const randNum = Math.floor(Math.random() * this.answerSouce.length) const selectedItem = this.answerSouce[randNum] if(!this.answer.includes(selectedItem)){ this.answer.push(selectedItem) } } }
async play(): Promise<void>{ let chFlg = false; while(!chFlg){ const inputArr = (await promptInput('「,」区切りで3つの数字を入力してください')).split(',') const result = this.check(inputArr) this.tryCount += 1 if(result.hit !== this.answer.length){ // 不正解だったら続ける printLine(`---\n Hit: ${result.hit}\n Blow: ${result.blow}\n---`) } else{ // 正解だったら終了 chFlg = true } } }
private check(input: string[]): {hit: number; blow: number}{ let hitCount = 0 let blowCount = 0 input.forEach((val, index) => { if(val === this.answer[index]){ hitCount += 1 } else if(this.answer.includes(val)){ blowCount += 1 } }); return { hit: hitCount, blow: blowCount, } }
end() { printLine(`正解です!\n 試行回数: ${this.tryCount}回`) process.exit() }
それでは、実際に$npm run build でコンパイルを行い、$npm run startで、動作を確認してみましょう。
今回の内容はいかがだったでしょうか。スクリプトを実行しながら動作確認できると面白いなと感じて頂けた方もいらっしゃるかもしれません。自分にできる範囲のものから少しずつJavaScriptにも挑戦してみようかなと思っていただければ幸いです。
以上となります。
参考文献:
・渡邊比呂樹『手を動かしながら学ぶTypeScript』シーアンドアール(2021年)