TypeScript 入門日記 02

前回

blog.takunology.jp

今回はこれを進めた。

docs.microsoft.com

型の宣言

JavaScript では letconst キーワードで変数を宣言できるが、どれも型推論。TypeScript では 変数名:型 で型を定義できる。

let x: number; // number 型になる
let y = 1; // 整数型として認識する
let z; // any 型として何でも入る

any みたいな全ての値を入れられる型だけでなく、プリミティブ型やオブジェクト、null を定義したりできる。

プリミティブ型

ブール型は boolean で定義

let flag: boolean;
let yes = true;
let no = false;

浮動小数点数number, BigInt は bigint で定義できる。BigInt は 8bit で数値の末尾に n をつける。

let x: number;
let y = 0;
let z: number = 123.456;
let big: bigint = 100n;

文字列は string で定義できる。文字列は二重引用符でも単一引用符でも宣言可能。

let s: string;
let empty = "";
let abc = 'abc';

複数行になる場合はバッククオート(`) を使用する。埋め込み式(文字列補間みたいなやつ)は ${} を組み込む。

let firstName: string = "Mateo";
let sentence: string = `My name is ${firstName}.
    I am new to TypeScript.`;

列挙型は C や C# と同じように enum で宣言してあげる。それぞれ値は 0 から割り振られるが、割り振る事もできる。

enum Hogehoge {
    hoge,
    huga,
    hugo
}

anyunknown はどんな値も入れられる型だが、後者は予期しないエラーを防ぐことができる。つまり、型チェックをかけられる。

アサーション

いわゆるキャストというやつ。例えば数値型を文字列型にしたい場合は as> で変換できるが、後者は jsx などの記法で HTML の始まりと間違えやすいのであまり使われない。

// 型アサーションと unknown によって型チェックが行われる。
let randomValue: unknown = 10;

randomValue = true;
randomValue = 'Mateo';

if (typeof randomValue === "string") {
    console.log((randomValue as string).toUpperCase());
} else {
    console.log("Error - A string was expected here.");
}

typeof を使用して条件式によって予め型を確認する方法を型ガードという。例えば、数値型であるかを調べるにはこのように書ける。

if (typeof randomValue === "number")

共用体型

変数を複数の型で定義する方法。型1 | 型2 というふうに書ける。

let multiType: number | boolean;

例えば、関数の引数の型を複数用意して、型ガードによって計算や文字列の連結を行うこともできる。

function add(x: number | string, y: number | string) {
    if (typeof x === 'number' && typeof y === 'number') {
        return x + y;
    }
    if (typeof x === 'string' && typeof y === 'string') {
        return x.concat(y);
    }
    throw new Error('型を揃えて出直してこいや');
}
console.log(add('one', 'two'));
console.log(add(1, 2));
console.log(add('one', 2));

交差型

2つ以上の型を結合して新しいプロパティを作成することができる。共用体と似ているが、型は最終的には1つになる。

例えば、それぞれ異なるプロパティを持つインターフェースを2つ用意して、それらを組み合わせることによって新しい型を作ることができる。

interface Employee {
  employeeID: number;
  age: number;
}
interface Manager {
  stockPlan: boolean;
}
type ManagementEmployee = Employee & Manager;
let newManager: ManagementEmployee = {
    employeeID: 12345,
    age: 34,
    stockPlan: true
};

リテラル

リテラルは直接な値を示すデータ。なので、最初にリテラルで定義されたデータ以外のものを受け付けなくすることができる。

// 文字列リテラル
type testResult = "pass" | "fail" | "incomplete";
let myResult: testResult;
myResult = "incomplete";    // OK
myResult = "pass";          // OK
myResult = "failure";       // OUT

// 数値リテラル
type dice = 1 | 2 | 3 | 4 | 5 | 6;
let diceRoll: dice;
diceRoll = 1;    // OK
diceRoll = 2;    // OK
diceRoll = 7;    // OUT

コレクション型

配列などのように連続したデータを格納できる。この辺は C# と似ている。

// 配列の定義
let list: number[] = [1, 2, 3, 4];

// ジェネリックを使う場合
let list: Array<number> = [1, 2, 3, 4]

この辺は開発者の好みらしい。

タプル

異なる型を配列として扱いたいときに使う。

let data: [string, number] = [`Hello`, 20];

サンプルプログラム

課題の4だけブログに記載しておく。元々の配列を空に設定しておけば、ランダムな数値を10個選んでくれる。何かしらの値で初期化しておくと、そこに追加でランダムな数値が追加される。

let randomNumbers: Array<number> = [];
let nextNumber;
for (let i = 0; i < 10; i++) {
    nextNumber = Math.floor(Math.random() * (100 - 1) + 1);
    randomNumbers.push(nextNumber);
}
console.log(randomNumbers);

実行結果

>node .\build\ex04.js
[
   2, 48, 40, 92, 11,
  14, 55, 30, 12, 44
]

配列に何かしらの値が含まれている場合

let randomNumbers: Array<number> = [0, 1, 2, 3];
>node .\build\ex04.js
[
   0,  1,  2,  3, 12, 66,
  70, 98, 28, 22, 92, 39,
  30, 58
]

イベントのお知らせ

2022年4月24日(日)に MS Tech Camp #14 を開催します。今回は私「たくのろじぃ」主催で、Blazor を使ったポートフォリオサイト製作と Azure Static Web Apps へのデプロイをやります。
興味がある方は(社会人、学生問わず)ぜひご参加ください!
Youtube での配信ですので、休日はごろごろしながらご覧いただければと思います。もちろん、一緒にやっていただいても結構です!

mspjp.connpass.com