6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

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 AppReact Nativeも公式にTypeScriptをサポートしています。

  • 静的型付け型推論Null 安全性という最近のプログラミング言語のトレンドを押さえつつ、それ以外の部分はそのまま JavaScript と同じ構文です。

  • 静的型付け言語は、コンパイルの段階でnullアクセスエラーになる可能性のコードをチェックして弾いてくれます。(null安全性)
  • 型推論とはいちいちプログラマが型を書かなくても、言語処理系が文脈から型を予測して型付けしてくれる機能のことです。
  • コーディング中にリアルタイムで問題箇所を指摘してくれるモダンなエディタのVS Code(IDE)が相性が良いです。
  • IDEとは統合開発環境のことで、コンパイラテキストエディタ、デバッガ、などを一つのUIから利用できるようにしたものです。
  • SlackもTypeScriptとReactで実装されています。

動的型付け言語と静的型付け言語の違い

動的型付け言語 : 変数などのデータ型の宣言がいらないプログラミング言語 (値やオブジェクトの型安全性を、実行時に検証する)

  • 変数の宣言時に型宣言をする必要がなく、実際にデータが入るタイミング(変数への代入時など)で方が自動的に決まるものです。

静的型付け言語 : 変数などのデータ型の宣言が必要なプログラミング言語 (値やオブジェクトの型安全性を、コンパイル時に検証する)

静的型付け

  • 変数や関数の引数および戻り値がプログラムの実行前にあらかじめ決まっている必要があります。

Null 安全性

  • アクセスエラーになる可能性のあるコードをコンパイルの段階で null チェックして弾いてくれます。(Ruby なら nil に対する NoMethodError)
let yano = {
  meshi: 'kimuti',
  skill: 'JavaScript'
}

// コードを実行する前に、コードを書いた瞬間エラーが出る。
yano.water // => Property 'water' does not exist on type '{ meshi: string; skill: string; }'.(2339)

4-2. TypeScript の基本的な型

アノテーション

// 数値型の変数を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ではプリミティブ型の特定の値だけを代入可能にする型を表現できます。そのような型をリテラル型と呼びます。 - 任意の文字列以外を許さない型です。
- オブジェクトリテラルとか配列リテラルとかのリテラルではありません。

  • リテラル型として表現できるものは、以下のようになります。
    1. 論理型のtrueとfalse
    2. 数値型の値
    3. 文字列型の文字列
// boolean型の中でもtrueの値しか受けつけないようにする
const isTrue: true = true;

// number型の中でも123の値しか受け付けないようにする
const num: 123 = 123;

// String型の中でも文字列fooの値しか受け付けないようにする
const str: "foo" = "foo";
  • JavaScriptconstを使って、変数宣言をすると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で列挙したリテラル型以外は受け付けないという書き方ができます。

参考

りあクト! 【Ⅰ. 言語・環境編】 p.149~162

サバイバルTypeScript-リテラル型