TypeScriptの変数
TypeScriptでは、変数の宣言はJavaScriptと同じルールに従います。
var、let、constを使って変数宣言をすることができます。
var
TypeScriptの変数は、JavaScriptと同じようにvarキーワードで宣言することができます。
スコープの規則もJavaScriptと同じです。
let
ES6では、var宣言の問題を解決するために、JavaScriptにletとconstというキーワードを用いた2種類の新しい変数宣言が導入されました。
JavaScriptのスーパーセットであるTypeScriptも、これらの新しいタイプの変数宣言をサポートしています。
let employeeName = "John";
// もしくは
let employeeName:string = "John";
let宣言は、var宣言と同じ構文になります。しかし、varで宣言された変数とは異なり、letで宣言された変数はブロックスコープを持ちます。
つまり、let変数のスコープは、関数、if elseブロック、ループブロックなど、そのブロックを含むものに限定されます。
次のような例で考えてみましょう。
let num1:number = 1;
function letDeclaration() {
let num2:number = 2;
if (num2 > num1) {
let num3: number = 3;
num3++;
}
while(num1 < num2) {
let num4: number = 4;
num1++;
}
console.log(num1); //OK
console.log(num2); //OK
console.log(num3); //Compiler Error: Cannot find name 'num3'
console.log(num4); //Compiler Error: Cannot find name 'num4'
}
letDeclaration();
上の例では、すべての変数がletで宣言されています。num3はifブロック内で宣言されているので、そのスコープはifブロック内に限定され、ifブロック外からアクセスすることはできません。
同様に、num4は whileブロックで宣言されているので、whileブロックの外からアクセスすることはできません。したがって、num3や num4をelse whereでアクセスすると、コンパイラのエラーになります。
同じ例でvar宣言をした場合は、エラーにならずにコンパイルされます。
var num1:number = 1;
function varDeclaration() {
var num2:number = 2;
if (num2 > num1) {
var num3: number = 3;
num3++;
}
while(num1 < num2) {
var num4: number = 4;
num1++;
}
console.log(num1); //2
console.log(num2); //2
console.log(num3); //4
console.log(num4); //4
}
varDeclaration();
一見varの方がエラーを出さないので便利に思えますが、こちらの方が予期せぬバグを生む可能性が高くなります。
varよりletを使用するメリット
let変数は、宣言される前に読み書きできない
console.log(num1); // Compiler Error: error TS2448: Block-scoped variable 'num' used before its declaration
let num1:number = 10;
console.log(num2); // OK, Output: undefined
var num2:number = 10;
上記の例では、TypeScriptコンパイラは、letで宣言する前に変数を使用するとエラーを出すが、varで宣言する前に変数を使用するとエラーを出しません。
let変数は再宣言できない
TypeScriptのコンパイラは、letを使って同じブロック内で同じ名前の変数(大文字と小文字を区別する)を複数回宣言すると、エラーを出します。
var num:number = 1; // OK
var Num:number = 2;// OK
var NUM:number = 3;// OK
var NuM:number = 4;// OK
let num:number = 5;// Compiler Error: Cannot redeclared block-scoped variable 'num'
let Num:number = 6;// Compiler Error: Cannot redeclared block-scoped variable 'Num'
let NUM:number = 7;// Compiler Error: Cannot redeclared block-scoped variable 'NUM'
let NuM:number = 8;// Compiler Error: Cannot redeclared block-scoped variable 'NuM'
上の例では、TypeScriptコンパイラーは変数名の大文字と小文字を区別して扱います。
numはNumと異なるので、エラーにはならない。しかし、同じ名前で大文字小文字を区別する変数についてはエラーとなります。
同じ名前と大文字小文字を持つ変数は、以下のように異なるブロックで宣言することができます。
let num:number = 1;
function demo() {
let num:number = 2;
if(true) {
let num:number = 3;
console.log(num); //Output: 3
}
console.log(num);//Output: 2
}
console.log(num); //Output: 1
demo();
同様に、以下のように、すでに関数の引数として渡された変数を宣言すると、コンパイラはエラーを出します。
function letDemo(a: number ) {
let a:number = 10 ; //Compiler Error: TS2300: Duplicate identifier 'a'
let b:number = 20 ;
return a + b ;
}
このように、letで宣言された変数は、コンパイラがコンパイル時にエラーを出すため、実行時のエラーの可能性を最小限に抑えることができます。
これにより、コードの可読性と保守性が向上します。
const
変数は、varやlet宣言と同様にconstで宣言することができます。
constは変数を定数化し、その値を変更できないようにします。const 変数は、let 変数と同じスコープルールを持っています。
const num:number = 100;
num = 200; //Compiler Error: Cannot assign to 'num' because it is a constant or read-only property
const変数は、1つの文の中で宣言し、初期化する必要があります。
const num:number; //Compiler Error: const declaration must be initialized
num = 100;
const変数は、オブジェクトのサブプロパティを変更することができますが、オブジェクトの構造を変えることはできません。
const playerCodes = {
player1 : 9,
player2 : 10,
player3 : 13,
player4 : 20
};
playerCodes.player2 = 11; // OK
playerCodes = { //Compiler Error: Cannot assign to playerCodes because it is a constant or read-only
player1 : 50, // Modified value
player2 : 10,
player3 : 13,
player4 : 20
};
以下のようにオブジェクト構造そのものを変更しようとしても、コンパイラがエラーを指摘します。
const playerCodes = {
player1: 9,
player2: 10,
player3: 13,
player4: 20
};
playerCodes = { //Compiler Error: Cannot assign to playerCodes because it is a constant or read-only
player1: 9,
player2: 10,
player3: 13,
player4: 20,
player5: 22
};