Open4
手を動かしながら学ぶ TypeScriptをやる
環境構築
package.jsonの準備
npm init -y
npm install -D typescript@4.3.5
「.ts」ファイルのコンパイル
mkdir src
touch src/index.ts
package.jsonの追記
{
"name": "handson-typescript",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc", // 追記
"dev": "tsc -w" // 追記
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"typescript": "^4.3.5"
}
}
tsconfig.jsonの追記
{
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
}
}
このタイミングで npm run dev
をしてdistディレクトリ内にindex.jsが追加されることを確認
strict trueを追記
{
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"strict": true
}
}
実行コマンドの追記
{
"name": "handson-typescript",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc",
"dev": "tsc -w",
"start": "node dist/index.js" // 追記
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"typescript": "^4.3.5"
}
}
npm start で書いたコードを実行!!
Node.js環境用のセットアップ
src/index.ts
を書き換える
const sayHello = (name: string) => {
return `Hello, ${name}`
}
pocess.stdout.write(sayHello('Michael Jackson'));
src/index.ts:5:1 - error TS2304: Cannot find name 'pocess'.
上記のようなエラーが出る。
これNode.jsの機能に関する型定義ファイルを用意していないから
下記コマンドで型定義ファイルをプロジェクトに追加する
ちなみに型定義ファイルはアプリケーションの実行時には使用しないので -D
オプションをつけている。
これは --save-dev
の省略形
npm install -D @types/node@16.4.13
これでエラーが出なくなる
対話用の関数を書いてみよう
printLine関数の追加
まずは受け取った値を出力するだけの関数を書く
src/index.ts
を以下のように書き換える
src/index.ts
const printLine = (text: string, breakLine: boolean = true) => {
process.stdout.write(text + (breakLine ? '\n' : ''))
}
promptInput関数の追加
次にユーザーに質問を投げかけ入力してもらうための関数を追加する
src/index.ts
const printLine = (text: string, breakLine: boolean = true) => {
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();
};
- 非同期処理でユーザーからの入力を待つ
-
process.stdin.once
はデータを一度だけ受け取る - 'data'イベントを登録することでユーザーがターミナルでエンターを押したタイミングで入力された文字列を読み取る
-
input.trim()
で入力された改行コードを取り除いている。process.stdin.once
で読み込んだデータは改行が含まれる為
動作確認
下記コードを追記して動作確認する
src/index.ts
(async () => {
const name = await promptInput('名前を入力してください')
console.log(name);
const age = await promptInput('年齢を入力してください')
console.log(age);
process.exit()
})()
ゲームの処理を書いてみよう
「HitAndBlow」クラスの作成
すべての処理を手続き型で書くとコードの見通しが悪くなってしまうらしい。だからHitAndBlowクラス
を作ってオブジェクト指向的にコードを書いていくらしい。
src/index.ts
class HintAndBlow {
answerSource: string[]
answer: string[]
tryCount: number
constructor() {
this.answerSource = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
this.answer = []
this.tryCount = 0
}
}
constructor内ではpropertyの初期化を行っている
インスタンスの作成
挙動を確かめるためHintAndBlow
クラスのインスタンスを作ってみる。
src/index.ts
(async () => {
- const name = await promptInput('名前を入力してください')
- console.log(name);
- const age = await promptInput('年齢を入力してください')
- console.log(age);
- process.exit()
+ const hintAndBlow = new HintAndBlow()
})()
クラスと型
VScodeで変数hintAndBlow
にカーソルを合わせるとhintAndBlow
はHintAndBlow型であることがわかる。TypeScriptでは宣言されたクラスを型情報として扱えるらしい。だから下記のように型アノテーションとしてもクラスを使える
const geme: HintAndBlow = new HintAndBlow()
まあクラスを型にできるゆーてもinterfaceで定義するのとほぼ変わらんらしい
以下とほぼ一緒
interface HintAndBlowInterface {
answerSource: string[]
answer: string[]
tryCount: number
}
##「 HitAndBlow」クラスのリファクタリング
さっき HitAndBlow」クラス作ったけど実はもっと短くかける
class HintAndBlow {
answerSource = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
answer: string[] = []
tryCount = 0
}