TypeScriptを始めよう:ビルドインタイプ

今日はTypeScriptのビルドインのデータタイプについて説明します。前回までの記事を理解していることが条件になりますのでご確認お願いします。

TypeScriptのビルドインタイプ

TypeScriptにはJavaScriptのデータタイプに加えられたものがあります。

JavaScriptTypeScript
number
string
boolean
null
undefined
object
左に加えて…
any
unknown
never
enum
tuple

ではテキストエディタを開いてコードを書いていきましょう!

数字を見やすくする

TypeScriptでは、数字のk(キロ:カンマの部分)はアンダースコアで記載することができます。

下記の例のように123_000_000は123,000,000と同じになります。もちろんこれはオプショナルなので使っても使わなくてもOKです。

let sales: number = 123_000_000;

データタイプを宣言する

下記のようにデータタイプを宣言することができます。

let sales: number = 123_000_000;

let course: string = "TypeScript";

let is_done: boolean = true;

ここで、初期の変数に値がある場合は変数のデータタイプをデフォルト値で固定できるのでデータタイプを外すこともできます。

let sales = 123_000_000;

let course = "TypeScript";

let is_done = true;

let myName;

ここでVSCodeでカーソルを変数の値にホバーするとデータタイプが表示されることが確認できます。

しかしlet myName;のようにデフォルト値を設定しないとTypeScriptが変数のデータタイプを判定することができません。

データタイプ:any

では.tsファイルに下記のような関数を作成してみます。

そうすると、因数のdocumentがハイライトされエラーが出ます。

エラーの内容はParameter ‘document’ implicitly has an ‘any’ typeで、documentにanyタイプのパラメーターが使用されています、です。

function render(document) {
  console.log(document)
}

//-(parameter) document: any
//Parameter 'document' implicitly has an 'any' type.ts(7006)

では、下記のようにanyのデータタイプを記載します。

function render(document: any) {
  console.log(document)
}

これでエラーが消えましたね。これは、データがどのタイプ(any)でも受け付けますと指示しています。これで開発する際にデータタイプを確認させるような仕組みになっているわけですね。

もし、このエラーを非表示にしたい場合はtsconfig.jsonファイルから設定を変更することができます。

// "noImplicitAny": true,

↓↓↓

"noImplicitAny": false,

このようにnoImplicitAnyをfalseにすることでエラーがなくなりました。実際にはTypeScriptはデータタイプのチェックのために使用するのでこの変更はできるだけしないようにしましょう。

配列:Array

JavaScriptの配列(Array)ではどのデータを使用することができます。

let numbers = [1, 2, "3"];

しかし、このようなストリングと数字の混ざったデータを計算させようとすると1+1=11のようになってしまい問題になりますね。

では、下記の様に数字のみの配列であることを宣言します。

let numbers: number[] = [1, 2, 3];

let numbers = [1, 2, 3];

もしくは、デフォルト値が数字だけの場合はnumber[]を外してもTypeScript側でデータタイプがnumber[]であることを認識してもらえます。

空の配列で数字のデータを受け入れる場合は下記の様にデータタイプを宣言しておくようにします。

let numbers: number[] = [];

VSCodeの推測機能

さらにTypeScriptを使う事でできるおまけの機能を紹介します。

TypeScriptではデータタイプを指定するのでVSCodeが次に来るメソッド等を予測して表示してくれます。

JavaScriptではできないことなので素晴らしいですね。

Tuple

Pythonを使ったことがある人は見たことがあるかもしれません。Tuple(タプル)はデータタイプが固定された配列のことです。よって配列の長さも変更できません。

let user: [number, string] = [1, "Ken"];

このように上記のTupleに3つ目のデータを追加しようとしたりデータタイプを変更したりしようとするとエラーになります。

それ以外の変更(値の変更)は可能です。

また、TypeScriptの強みとしてこのように数字のデータに対してのメソッドと次のスクリーンショットのストリングに対するメソッドがそれぞれ表示されるのでとても使いやすくなります。

数字のデータに対してのメソッドの予測表示
Iストリングのデータに対するメソッドの予測表示

列挙型(Enums)

列挙型は、関連する値の集合を編成する方法です。これを使用することで関連する変数をセットとして一つのenum内にまとめることができます。

下記のsmallとSize.Smallは同じものになります。ちなみにenumで宣言する変数名は大文字で始まり、中の変数も大文字で始めることが慣習とされています。

const small = 1;
const medium = 2;
const large = 3;

enum Size {
  Small = 1,
  Medium,
  Large,
}

console.log(small); //1
console.log(Size.Small); //1

上記のコードは下記のコマンドで実行できます。

node dist/index.js

このようにsmallとSize.Smallは同じ値になることがわかりますね。

ここでコンパイルされた.jsファイルを見ると中身がすごいことになっていることに気が付きます。

dist/index.js

"use strict";
const small = 1;
const medium = 2;
const large = 3;
var Size;
(function (Size) {
    Size[Size["Small"] = 1] = "Small";
    Size[Size["Medium"] = 2] = "Medium";
    Size[Size["Large"] = 3] = "Large";
})(Size || (Size = {}));
console.log(small);
console.log(Size.Small);
//# sourceMappingURL=index.js.map

この変数を詳しく見てみましょう。

var Size;
(function (Size) {
  Size[(Size["Small"] = 1)] = "Small";
  Size[(Size["Medium"] = 2)] = "Medium";
  Size[(Size["Large"] = 3)] = "Large";
})(Size || (Size = {}));

console.log(Size);
console.log(typeof Size);

//結果
node dist/index.js

{
  '1': 'Small',
  '2': 'Medium',
  '3': 'Large',
  Small: 1,
  Medium: 2,
  Large: 3
}
object

そうすと、データタイプがオブジェクトで返ってきました。これは変数 Sizeで設定したものをJSのランタイムで実行できる関数でオブジェクトに変換したわけですね。ちなみに(functjion(){})の関数を括弧で囲っているのはimmediately invoked function、もしくはIIFE即時実行関数式といいます。これはあとから関数()を呼んだものと同じですが、その場で実行できるショートカットのようなものです。

ではconst enumを見てみます。

const enum Size {
  Small = 1,
  Medium = 2,
  Large = 3,
}

console.log(Size); //これはエラーになります。
console.log(Size.Small);

このようにenumをconstで宣言すツことができます。しかし、Size自体を呼ぼうとするとエラーになってしまいます。

ではコンパイルされたファイルを見てみましょう。

console.log(1 /* Size.Small */);

なんと、前の方法で作成されたSizeオブジェクトが作成されず、実際に使用したSize.Smallの値がそのまま書き出されてしまいました。

この方法は最初の方法よりよりパフォーマンスが良いですが、リアクティブな動作をしたい場合は使わない方がよさそうですね。

今日はここまで!

お疲れ様でした。