チャチャチャおもちゃの抹茶っちゃ

ゲームのこととかプログラミングのこととか。気が向いたら書く。ブログタイトルは友人が考えました。

【TypeScript】TypeScriptのすすめ [おまけ:CLIアプリケーションをつくる]

はじめに

この記事は CCS Advent Calendar 2020の15日目の記事です。

adventar.org

えびてんくんの記事: 土鍋による炊飯←前|次→でんちゅらくんの記事: 冬にはオススメ出来ない都内の歩き方

TypeScriptはいいぞ

突然ですが弊サークルでは新入生にはC言語を教えることが多いです。C言語だったりC++を使ってWindowsアプリケーションとしてゲームを作っている会員がほとんど。自分もC++好きです。闇もありますが楽しい言語ですよね。

ところが最近、ぼくはC++から離れてしまっています。というのも、普段のアルバイトだとか研究だとかで主にいじっているのがWebアプリケーションなため。C++でもWebAssenblyとかあるけど、基本的にはWebアプリケーションをつくるのにC++を選択する人はそういないんじゃないですかね。(サーバー部分だけとかはあるだろうけれど......)

Web系の言語だと多くの人が思い浮かべるのはそう、JavaScriptだと思います。当然ぼくもWebApp周り触るにあたってJavaScriptを触るわけなんですが.....、気分が悪くなってきました。普段からクラスベースで開発して、静的型付け言語ばかり触ってきた身には呼吸が大変しづらいです。

そこで!!TypeScriptの出番です。

TypeScriptって何よ?JavaScriptとどう違うの?

TypeScriptはJavaScriptのスーパーセット、強化版。これだけで強そう。 JavaScriptに対して静的型付けとクラスベースのオブジェクト指向をとりいれたものがTypeScriptで、JavaScriptアプリケーションの開発が可能です。なんと開発元は天下のMicrosoft

仕組みはかんたんで、JavaScriptの文法を強化したTypeScriptファイルを記述したあと、TypeScriptコンパイラJavaScriptファイルに変換してくれます。コンパイルというけれど、やっていることはコードの変換なのでトランスコンパイル

f:id:mattyan1053:20201215172846p:plain
TypeScriptで書いたファイル(左)と変換して生成されたJavaScriptファイル(右)

こんなかんじ。TypeScriptで書いたもののほうがC++erには馴染み深い感じがするのではないでしょうか?

TypeScript で開発されているもの

github.com

ぼくもだいすきVSCode、TypeScriptで開発されています。確認したらコードの実に93.7%がTypeScriptでした。

TypeScriptのいいところ

型付けができる

まずコレを見てください。

let str="hello";
str=123;

JavaScript、これが許されます。は? いやまあそういうものなのだけれど......。TypeScriptならこんなことは"ちゃんと"できません!!頑張ってやろうとするなら

let str: string | number = "hello"
str=123

と二種類の型を取ることを明示することで不明瞭な感じを排除できます。これはうれしい!一発でstrstring型かnumber型のどちらかであることがわかりますね(変数名の話はここではおいておいて)。

さて、これ変数の型でも嬉しいですが、特に顕著なのが関数に渡す値の型や返ってくる値の型が明瞭なところです。

function add(a, b) {
    return a + b
}

const ans = add(x, y)

こんなコードがあったとする。このコードのadd()関数、渡す引数が数値でなくて文字列でもうまく動いてしまいます。でもこの関数を作った人はそんなことは想定していないかもしれません。そこでTypeScriptを使うと

function add(a: number, b: number) {
    return a + b
}

これならこの関数の引数がnumberであることも丸わかり、なんなら返り値までnumberであることが保証されます。すばらしい!!!JavaScriptあるあるだと思うんですが、この渡すものが構造体的な大きなものになってくるとどんどん怪しくなってくるんですよね......それが防止できます。 さらに言えばちゃんとしたエディタならこれらのことからエラーチェックもできるようになるんですよね。実行時エラー防止!

クラスを使える

コレは少し語弊があって、JavaScriptでもクラスは使えるんですが......(ES6以降class構文が導入された)、JavaScriptのクラスっぽい何か、C++とかやっていた身からすると使いづらくないですか?TypeScriptを導入することですんなりとクラスを使うことができます。やったー!

トランスコンパイルのパワー

TypeScriptはそのコードから変換することでJavaScriptを生成します。つまりその変換先のJavaScriptをコントロールできるということになります。最新のTypeScriptコードから、変換先のJavaScriptを古いものにすれば古い環境でも動かすことができる!すごい!

JavaScriptも動く

警告等は出ますが、JavaScriptのコードをTypeScriptとしてベタ貼りしても動かすことができます。つまり今までのJavaScriptをTypeScriptに移行するのも一気にやる必要がないですね!

実際にTypeScriptを書いてみる

このへんはぐぐったら似たような記事たくさん出てきそう。雑にいきます。「Node.js」ってやつを使います。

環境構築

とりあえずNode.jsで検索してダウンロードしてインストールしましょう。homebrewとかaptとかでもあります。さて、node.jsがインストールしおわったら、npmというコマンドが使えるようになっているんじゃないでしょうか。 npmはnode.jsのパッケージマネージャです。プログラムを書いていると、他の人が作ったライブラリとかを使うこともあると思います。このへんをよしなに導入してくれるすごいやつです。とはいえ、このnode.jsのパッケージマネージャはnpm以外にもあって、ぼくはyarnってのを使っています。

ってことでyarnが使える前提で話を進めていきます。

$ mkdir hello-typescript
$ yarn init

適当なところに練習用のディレクトリを作成して、そこでyarn initコマンドを実行します。いろいろ聞かれるので適当に答えていくとpackage.jsonが生成されます。ここにはライブラリの情報とかもはいっているので、gitとかから同じものをDLした人は、yarn installするだけで自動で環境構築されます。便利。Pythonpipenvみたいなやつよね。

これでNode.jsを使ってJavaScriptを書くことができるようになりました。とはいえ、まだTypeScriptが書けないのでかけるようにします。

$ yarn add typescript @types/node
$ yarn run tsc --init

次にpackage.jsonを開いてyarnが勝手にコンパイル&実行までしてくれるコマンドを記述。tsc -p .でTypeScriptファイルをコンパイルしてnode .で実行。

{
  (略)
  "scripts": {
    "start": "tsc -p  . && node ."
  },
  (略)
}

これで準備OK。あとは適当にindex.tsを作って

const str: string = "Hello TypeScript!"
console.log(str)

実行してあげると

$ yarn run start
Hello TypeScript!

うまく実行できて、index.jsファイルも生成されていることがわかる。ちなみに

$ yarn add ts-node

ts-nodeをインストールして

{
  (略)
  "scripts": {
    "start": "ts-node ."
  },
  (略)
}

とするとjsファイルを残さずに一気に実行までやってくれる。ts-node便利。

これで好きにTypeScriptがかけるようになりました!

TypeScript で CLI アプリケーションを作る

これはおまけなんですが、せっかくTypeScriptがかけるようになったのでなんか作ってみます。TypeScriptはJavaScriptの強化版なので、JavaScript用にライブラリが出ていれば使うことができます。そして世の中はJavaScript向けにライブラリを提供しているもので溢れています。今回はGoogleさんの力を借りてみることとします。ちょっとCloud Vision APIで遊んでみようかなって。

はじめるまえにライブラリのインストール

yarnさんがいるので一瞬です。コマンドラインで入力するので、引数のパーサーもいれておきます。Pythonのargparseとだいたい同じやつです。

$ yarn add @google-cloud/vision argparse
$ yarn add -D @types/argparse

使うライブラリのドキュメントたち↓

cloud.google.com

github.com

コードを書く

書くだけ。

index.ts

import { ArgumentParser } from "argparse"
import { VisionApi } from "./lib/google/VisionApi"

async function main() {
    const parser = new ArgumentParser({
        description: 'Text Detection (Google Cloud Vision API - OCR -)',
        add_help: true
    })
    parser.add_argument('-p', '--path', {help: "image file path or URL", required: true})
    const args = parser.parse_args()

    const va = new VisionApi()
    va.detectText(args.path)

}

main()

これTypeScriptすごい!ポイントなんですけど、ArgumentParserの引数とかadd_argumentの引数で複数の値の塊渡す時にちゃんと型の補完が入ってくれるんですよね。なので実行時に型が実は違った!みたいなエラーを回避できます。嬉しい。

VisionApi.ts

import { ImageAnnotatorClient } from "@google-cloud/vision"

export class VisionApi {
    async detectText(fileName: string) {
        const client = new ImageAnnotatorClient()
        const [ result ] = await client.textDetection(fileName)
        const detections = result.textAnnotations
        console.log('Text: ')
        detections?.forEach( text => {
            console.log(text.description)
        })
    }
}

実行

画像から文字を抽出してくれます。精度はそれなり。手書きはきつそう。

$ gcloud auth login
$ yarn run start

f:id:mattyan1053:20201215183310p:plain
英語はいけそう

f:id:mattyan1053:20201215183525j:plain
千業大学電子計算機研究会
 
f:id:mattyan1053:20201215183649j:plain
雑に書いたらもうだめ

よく見たら紙の「Date」正確に読み取ってて笑った。

作ったやつ

github.com

ちょっとあとからコマンド追加できたりするように調整してあるよ。

さいごに

TypeScriptの紹介とおまけはこれでおわり!みんなもぜひTypeScript触ってみてね!

ちなみにTypeScriptでデスクトップアプリもつくれます(VSCodeがまさにそう)。TypeScriptとHTMLとCSSを組み合わせてUIを作れたりするので、TypeScriptでゲームを作ってみたりするのも面白い......かも?