Open14
TypeScriptを学ぶ

【❓】なぜ型があるのに型推論があるのか
- 型推論はコンパイルのタイミングで型が決定され、その型が変更されることはない
- 型をプログラマが書くかコンパイラが自動で決めるか
- 動的型付けでは実行時に型が決まるので、実行タイミングにより型が変化
- 型注釈を省略できるので、コードの記述量を減らせる
参考文献

JavaScriptエコシステム
TypeScriptが解決すること
- 静的型検査により、実行前に型の不具合を検出する。これは大規模開発において便利。
TypeScriptはトランスパイラ
- TSはJavaScriptにコンパイルするトランスパイラ
- CoffeeScriptやDartもトランスパイラ
- JSにコンパイルして使う言語をAltJSと呼ぶ
TypeScriptと関係のある技術
- モジュールバンドラ
- モジュールバンドラとは、複数のJSを一つのJSに統合するためのツール
- 目的は、JSだけでなく、CSSなども結合してブラウザに配信しやすくすること
- webpackやparcelなど
- タスクランナー
- タスクランナーとは、ある決められた処理を実行しやすい形にまとめて、実行の順序を意識せず実行できるようにするツール
- gulpやgruntなど
- パッケージマネージャ
- パッケージマネージャとは、JSのライブラリをネットで公開し、誰でも使えるようにすることと、自分が作っているプログラムがどのライブラリに依存しているかを記述すると自動的にインストールする"便利なやつ"
- npmやyarnなど
- 実行環境
- JSはコンパイルして機械語にすることはできない。Node.jsやブラウザなどの実行環境を要する
- コードフォーマッター
- コードフォーマッターとは、あるルールに従いソースコードのタブやインデントなどの表記揺れを整形する
- PrettierやESLintなど

【❓】パッケージマネージャ結局なんなのかわからん
OSやプログラミング言語といった、ひとつの環境で、各種のソフトウェアの導入と削除、そしてソフトウェア同士やライブラリとの依存関係を管理するシステム (Wikipedia "パッケージ管理システム"より)

ECMAScript
- ECMAScriptはJavaScriptの仕様。TypeScriptもECMAScriptに準拠している。
- ECMAScriptが定める範囲は、言語の文法、構文の解釈方法、コアのAPIなど言語の中核部分
- ECMAScriptは毎年1回、仕様改定される

let, const, var
- let と const
- letは初期値不要、再代入可能
- constは初期値必要、再代入不可
- 基本はconstで変数宣言をして必要な場合にのみ、letを使う
- constで変数宣言することで再代入を禁止して、意図せず変数が書き換えらることを予防できるので、より安全なコードになる
- varはもう使わない
- ❌varの変数宣言では同じ変数名で宣言をした場合にエラーとならずに、後から宣言された変数が有効となる
- ❌varはグローバル変数として定義でき、グローバル変数として定義されたときに、windowオブジェクトのプロパティとして定義されるため、既存のプロパティを上書きする危険性がある
- 変数の巻上げ
- JavaScriptで宣言された変数はスコープの先頭で変数が生成される←変数の巻き上げ
- ❌varで宣言された変数は、スコープの先頭で生成されてundefinedで値が初期化される
- ✅letとconstでは、宣言前の変数を参照するとReference Errorが発生する

プリミティブ型
- JavaScriptのデータ型は、プリミティブ型とオブジェクトの2つに分類される
- プリミティブ型の特徴
- 値を直接変更できない。イミュータブル
- 基本的にプロパティを持たない
- boolean, number, string, undefined型, null型, シンボル型, bigint型
- オブジェクト
- 値を後から変更できる。ミュータブル

【❓】なぜプリミティブ型とオブジェクトの2つが用意されているのか

number 数値型
- 数値の区切り文字
- JavaScriptの数値リテラルは可読性のためにアンダースコアで区切って書ける
100_000_000 //1億
- NaN
- 非数(not-a-number)を表す変数
- 処理の結果、数値にならない場合にNaNを返すことがある
- NaNは特殊で、等号比較では常にfalse
- Infinity
- 無限大を表す変数
- たとえば、1を0で割った場合、この値になる

string 文字列型
- ダブルクォートでもシングルクォートでもまったく同じ文字列型
- バッククォート`で囲んだ文字列はテンプレートリテラル(template literal)と言う
const count = 10;
console.log(`現在、${count}名が見ています。`);
// 現在、10名が見ています。

null型, undefined型
- null型:JavaScriptのnullは値がないことを示す値
- undefined型:JavaScriptのnullは値がないことを示す値
- nullは自然発生しない
- 特にこだわりがないのなら、TypeScriptではnullは使わずにundefinedをもっぱら使うようにする

bigint型 (big intenger)
- JavaScriptのbigint型は、数値型よりも大きな整数を扱えるプリミティブ型
- JavaScriptのbigint型のリテラルは整数値の末尾にnをつけて書く
- bigint型はBigInt関数を使って作ることができる
- bigint型と数値型はそのままでは一緒に演算をすることはできない
- 数値型が小数部を持っていない限り、より表現幅の広いbigint型に合わせる方が無難

型強制
- JavaScriptにはデータ型がありますが、型が異なる2つの値に対し演算してもエラーにならない場合がある
- これは型強制(type coercion)と呼ばれる仕組みによるもの
- 型強制とは、型が異なる2つの値を処理するとき、暗黙的に別の型へ変換されること

ボックス化
- リミティブからオブジェクトへの変換をボックス化(boxing)と言う
// プリミティブ型
const str = "abc";
// ラッパーオブジェクトに入れる
const strObject = new String(str);
// オブジェクトのように扱う
strObject.length; // フィールドの参照
strObject.toUpperCase(); // メソッド呼び出し
- 実際のコードでは、プリミティブ型をStringのようなラッパーオブジェクトにわざわざ入れる必要はない。JavaScriptには自動ボックス化という仕組みがあるので。
const str = "abc";
// オブジェクトのように扱う
str.length; // フィールドの参照
str.toUpperCase(); // メソッド呼び出し
- このようなことができるのは、JavaScriptが内部的にプリミティブ型の値をオブジェクトに変換しているから
- ラッパーオブジェクト
- JavaScriptの自動ボックス化で変換先となるオブジェクトをラッパーオブジェクト(wrapper object)と呼ぶ
- ラッパーオブジェクトとTypeScriptの型
- TypeScriptでは、ラッパーオブジェクトの型も定義されている
- ラッパーオブジェクト型の変数にプリミティブ型の値を代入するのも可能
- しかし、ラッパーオブジェクト型はプリミティブ型に代入できない

any型
- どんな型でも代入を許す型
- 型を省略してコンテキストから型が推論できない時、TypeScriptは暗黙的に型をany型として扱う