2022年3月21日 りあクト! 第4章 TypeScriptで型をご安全に(p.149~162)
4-1. TypeScript はイケイケの人気言語?
- TypeScriptは、AltJS (JS) の代替言語。最終的にコンパイラによってJSのコードに変換されます)の1つです。Alternative JavaScriptの略で別のJavaScriptという意味になります。
- GitHut というサイトでは、最新の2020年第3クォーターのプルリクエストベースのランキングでTypeScriptが5位に入っています。(Rubyは7位)
Create React AppやReact Nativeも公式にTypeScriptをサポートしています。
静的型付け、型推論、Null 安全性という最近のプログラミング言語のトレンドを押さえつつ、それ以外の部分はそのまま JavaScript と同じ構文です。
- 静的型付け言語は、コンパイルの段階でnullアクセスエラーになる可能性のコードをチェックして弾いてくれます。(null安全性)
- 型推論とはいちいちプログラマが型を書かなくても、言語処理系が文脈から型を予測して型付けしてくれる機能のことです。
- コーディング中にリアルタイムで問題箇所を指摘してくれるモダンなエディタのVS Code(IDE)が相性が良いです。
- IDEとは統合開発環境のことで、コンパイラ、テキストエディタ、デバッガ、などを一つのUIから利用できるようにしたものです。
- SlackもTypeScriptとReactで実装されています。
動的型付け言語と静的型付け言語の違い
動的型付け言語 : 変数などのデータ型の宣言がいらないプログラミング言語 (値やオブジェクトの型安全性を、実行時に検証する)
- 変数の宣言時に型宣言をする必要がなく、実際にデータが入るタイミング(変数への代入時など)で方が自動的に決まるものです。
静的型付け言語 : 変数などのデータ型の宣言が必要なプログラミング言語 (値やオブジェクトの型安全性を、コンパイル時に検証する)
静的型付け
- 変数や関数の引数および戻り値がプログラムの実行前にあらかじめ決まっている必要があります。
Null 安全性
let yano = { meshi: 'kimuti', skill: 'JavaScript' } // コードを実行する前に、コードを書いた瞬間エラーが出る。 yano.water // => Property 'water' does not exist on type '{ meshi: string; skill: string; }'.(2339)
4-2. TypeScript の基本的な型
型アノテーション
- 変数に型の注釈を付けることです。
- 型アノテーションを行うと、静的に型付けされた情報はコンパイル時のチェックに用いられ、書かれたコード中に型の不整合があるとコンパイルエラーが起こります。
value:type
というフォーマットで予め型を宣言出来るものが型アノテーションです。- 型アノテーションによって型付けしない場合は型推論が行われます。
// 数値型の変数をnとして宣言し、その変数に3を代入する let n: number = 3; // 数値型以外の値を代入するとエラーが出ます let n: number = '3'; // => Type 'string' is not assignable to type 'number'.(2322)
配列の型の中身は全てnumber型の場合の型アノテーション
const numarr: number[] = [1, 2, 3];
型推論
JavaScriptの暗黙の型変換
ある処理において、その処理過程で行われる明示的ではない型変換のこと(JavaScriptPrimer)
const s = '123'; > s * 3 > // => 369
- 文字列に対して3をかけていますが、計算できているのは文字列が暗黙的に数値に変換されているからです。
TypeScrptのプリミティブ型
JavaScriptのプリミティブ型と同じ7種類です。
- Boolean ⇒ true falseの真偽値
- Number ⇒ 数値
- BigInt ⇒ numberでは表現できない大きな数値(253以上)
- String ⇒ 文字列
- Symbol ⇒ シンボル値という固有の識別子を表現する値
- Null ⇒ 何のデータも含まれない状態を明示的に表す
- Undefined ⇒ 未定義であることを表す
配列を型アノテーションを使って宣言する
①配列リテラルを使う方法
// String型の配列を作成して変数yanoに代入する。 const yano : string[] = ['kimuchi', 'tofu', 'nattou']
②ジェネリクス<>
を使う方法
const yano : Array<string> = ['kimuchi', 'tofu', 'nattou']
①のリテラルを使う方法が推奨されているのでジェネリクスの書き方はこういった書き方もできるという認識だけ持っておけば良いでしょう。
型アノテーションにオブジェクトを使うときの書き方
Objectはプリミティブ型以外の全てのオブジェクトのプロトタイプなのでobjectと型アノテーションに定義すると広義になり意味をなさないものになります。
const words: object = ['a', 'b', 'c'];
狭義のオブジェクトの型を定義する書き方
const red: { rgb: string, opacity: number } = { rgb: 'ffff', opacity: 1}
このように毎回インラインで書くのが大変なため インターフェースというオブジェクトの型に名前を付ける宣言の仕方があります。
// colorというインターフェースを作成し、オブジェクトで使われるであろうキーとその型を宣言する interface Color { readonly rgb: string; opacity: number; name?: string; } // turquoiseというオブジェクトにcolorインターフェースを適用したプロパティとその値を代入する。 const turquoise: Color = { rgb: '00afcc', opacity: 1 }; // turquoiseオブジェクトのnameプロパティに文字列型の値を代入 turquoise.name = 'Turquoise Blue'; turquoise.rgb = '03c1ff'; // error TS2540: Cannot assign to 'rgb' because it is a read-only property.
?
をつけるとそのキーは省略できます。今回の例ではname
です。readonly
をつけると書き換え不可になります。
インデックスシグネチャ
[key: T]: U
という構文は、インデックスシグネチャと呼ばれます。これは、オブジェクトがより多くのキーを含む可能性があることをTypeScriptに伝える方法です。- キーを文字列と数値の2種類なら何が入っても使用できるというものです。
interface Status { [attr: number]: boolean; } const myStatus: Status = { 1: true, 2: false, 3: true } console.log(myStatus);
- キーは
number
型なら何でも許可し、バリューはboolean
型を指定しています。
TypescriptのEnum型、共用体型
enumは宣言とキー名を最初の文字を大文字で書くという慣例があります。
リテラル型とは
TypeScriptではプリミティブ型の特定の値だけを代入可能にする型を表現できます。そのような型をリテラル型と呼びます。 - 任意の文字列以外を許さない型です。
- オブジェクトリテラルとか配列リテラルとかのリテラルではありません。
- リテラル型として表現できるものは、以下のようになります。
- 論理型のtrueとfalse
- 数値型の値
- 文字列型の文字列
// boolean型の中でもtrueの値しか受けつけないようにする const isTrue: true = true; // number型の中でも123の値しか受け付けないようにする const num: 123 = 123; // String型の中でも文字列fooの値しか受け付けないようにする const str: "foo" = "foo";
- JavaScriptのconstを使って、変数宣言をするとTypeScriptではリテラル型として型推論されます。なぜなら、constで宣言された変数には再代入できないため自動的にリテラル型として初期化された値しか受け付けないようになるのです。
let x = 1; // let x: number const y = 1; // const y: 1
共用体型
let x: number | string; x = 'yano'; x = 2; x = true // => Type 'boolean' is not assignable to type 'string | number'.
- 変数xは
number
またはstring
のみを受け付けるという型を指定できています。
let asakai: 'yui' | 'yuki' | 'yano' = 'yui'; console.log(asakai); // => yui asakai = other; // => [ERR]: other is not defined
- 変数
asakai
で列挙したリテラル型以外は受け付けないという書き方ができます。