【TS】公式ドキュメントから学ぶTypeScript(1. 基礎編)
はじめに
- ReactやNext.jsでもTypeScriptは欠かせないため、公式ドキュメントで学んだ内容を記事にしており、今回は基礎編になります。
- 前回の記事も置いておきますので、「TypeScript興味あるけどやったことないよ〜」という方はぜひご覧ください🙌
TSファイルからJSファイルの生成
TypeScript自体をブラウザは認識することが出来ません。
そのため、TypeScriptをJavaScriptに変換(コンパイル)する必要が出てくるわけです。
この変換には、tscというトランスパイラを使用します。
npm install -g typescript
ここで、以下のようにhello.tsというファイルを作成したとしましょう。
// Greets the world.
console.log("Hello world!");
hello.tsをtsファイルからjsファイルにコンパイルするには、以下コマンドを実行します。
tsc hello.ts
この操作で、hello.jsというファイルが新たに生成されます。
では、tsファイルにエラーがあった場合はどうでしょう?
hello.tsを以下のように書き換えてみましょう。
- // Greets the world.
- console.log("Hello world!");
+ // This is an industrial-grade general-purpose greeter function:
+ function greet(person, date) {
+ console.log(`Hello ${person}, today is ${date}!`);
+ }
+ greet("Brendan");
編集後にtscコマンドでコンパイルすると...
Expected 2 arguments, but got 1.
コンソール上でエラーがあると知らせてくれます。
ただし、エラーが見つかってもそのままjsファイルを生成されてしまうようです。
これは嬉しくないですよね...。
コンパイル時にエラーがあった時にjsファイルを生成しない方法として、tscコマンド実行時にオプション--noEmitOnErrorを渡す方法が挙げられます。
tsc --noEmitOnError hello.ts
型の明示
先ほどのhello.tsでは、greet関数の引数がどんな型なのか指定していませんでしたね。
以下のように記載することで、型の指定が可能です。
ついでに、先ほどエラーが出たgreet関数の呼び出しも併せて修正しています。
// This is an industrial-grade general-purpose greeter function:
- function greet(person, date) {
+ function greet(person: string, date: Date) {
console.log(`Hello ${person}, today is ${date}!`);
}
- greet("Brendan");
+ greet("Maddison", new Date());
なお、TypeScriptでは必ずしも型を明示しなくても良いとされています。
TypeScriptが、開発者の意図する型と同じものを推測できる場面では、アノテーションをつけない方が可読性が上がるなどの利点があります。
以下のコードでは、文字列を代入していることから明らかにmsgはstring型と推測できますね。
let msg = "hello there!";
コンパイル後のコード
先ほどアノテーションを追加したhello.tsのコンパイル後に生成されるhello.jsを見てみましょう。
"use strict";
function greet(person, date) {
console.log("Hello ".concat(person, ", today is ").concat(date.toDateString(), "!"));
}
greet("Maddison", new Date());
型アノテーションがなくなっていますね。
本記事の冒頭でもチラッとお話しましたが、ブラウザはTypeScriptを解釈・実行することが出来ません。
そこで、型チェックといったエラーの有無の確認をコンパイル時に行い、ブラウザが解釈・実行できるJavaScriptファイルへと変更したのです。
もう少しよく見てみると、console.logの中身の文字列も若干異なっていますね。
これは、TypeScriptがコンパイル時に使用するJavaScriptのバージョンにあります。
hello.tsでは、バッククォートで囲む「テンプレート文字列」を使用していますが、この機能を使うことができるJavaScriptのバージョンは ECMAScript 2015 (ES6) です。
一方で、コンパイル後に生成されたhello.jsのバージョンは ECMAScript 5 (ES5) と古いバージョンのため、テンプレート文字列が使えずにコードが微妙に異なっているのです。
このような事象を回避したい場合、tscコマンド実行時にtargetオプションを渡すと良いでしょう。
tsc --target es2015 hello.ts
型チェックの厳しさの調整
型チェックにも色々な種類があり、デフォルトでは全て無効化されています。
strictオプションで全て有効化することもできますし、個別に設定することも可能です。
公式ハンドブックでは、以下2つについて言及されています。
noImplicitAny
関数の引数や変数の初期値がない場合、TypeScriptは型推論を行う事ができる、any型を割り当てます。
このany型は「なんでも代入できる型」であり、通常のJavaScriptの仕様に戻ってしまうわけです。
しかし、そもそもTypeScriptを使用する目的は「型を割り当てることによりエラーを防ぐ」ことであるため、このany型を使用することは推奨されません。
noImplicitAnyを有効にすることで、暗黙的に割り当てられるany型が存在した場合、エラーとして表示してくれるようになります。
strictNullChecks
通常のJavaScriptではnullやundefinedはどのような変数にも割り当てることが出来ます。
それ故、想定していない場面で変数にnullやundefinedが代入されてしまう事態が頻発します。
このような事象を回避するためstrictNullChecksを有効化することで、型定義でnullやundefinedを設定した変数にのみ、nullやundefinedを割り当てる事ができるようになります。
補足
tscコマンド実行時のオプションであったり、noImplicitAnyやstrictNullChacksを有効 / 無効にする設定は、tsconfig.jsonを作成して管理すると良いでしょう。
以下、公式ドキュメントですのでご参考までに...
終わりに
型チェックの厳しさも調整する形なのは少し意外でした。
結構設定することが多そうだけど、現場ではどのようにして決めるのかなぁ...
tsconfig.jsonも深掘りしたいし、公式ハンドブック読みきれてないし、てんてこ舞いだ🫠
Discussion