TypeScript文法(基礎編) 変数とは何かから解説

# TS Playground
TypeScriptの文法を試す際、
playgroundを使うと手軽で便利。
https://www.typescriptlang.org/play

# 変数とは

変数とは、
よく箱に例えられることが多いが、
そもそも素朴な疑問としてなぜ箱が必要なのか思うはずだ。

変数は確かに値が入っている箱ではあるのだが、
そうした箱を使う理由は、
**値などに名前をつけたいからと考えればいい。**

例えば、
ラーメン屋の売上が100000円で、
曜日によって、
ラーメン屋の売上から1000円引いたり、
300円引いたりと、売上額に対して色々計算をする場合、
変数を使わないと、
```
console.log(100000 - 1000)
console.log(100000 - 300)
```

のように、パット見上の数字が何を表しているのかよくわからない。

そこで変数を使って、
それぞれをいわゆる箱に入れると、
変数名に好きな名前をつけることができるので、
(※変数名にできないものもあるがそれは後ほど解説する)

```
const uriage = 100000
console.log(uriage - 300)
console.log(uriage -1000)
```
というふうに、売上から何かを引いているということが
わかる。

実際は、上記のような処理の際は関数を使うのがいいのだが
(関数も名前をつけられる)

変数の利点はこれ以外にも色々あるのだが、
一旦、名付け機能が強力だからという印象で問題ない。
(変数の名付けはものすごく奥が深い)


# TypeScriptの変数
TypeScriptのベースは、
JavaScriptなので、型以外は、
基本的に変数宣言のやり方は同じだ。

型をつけないで、変数宣言をすることもできるので、
下記のようにJavaScriptと同じ文法で変数定義することもできる。

```:index.ts
const hello = 'Hello'
console.log(hello) // 'Hello'と表示される
```

ちなみに、
**一行コメントは、//で行い、
複数行コメントは、/*...*/で行う。**


# 変数名としてつかえないもの

上記で名付けが強力といったが、
何でも好きな名前をつければいいというわけでもない。

まず**予約語**は変数名には使えない。
予約語とは、ifやforなど、TypeScriptのなかで予め用意されているものだ。

基本的には、JavaScriptの予約語と変わらないはずだ。
ここにJavaScriptの予約語が書かれている。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Lexical_grammar


ただ、変数の名付けは、基本的に他のプログラマーがわかるような変数にするため、
正直予約語と衝突することはあまりない。
(予約語を変数名に使っている時点で変数名としては良くないからだ)

一応、日本語も変数名にすることは、
可能っちゃ可能だ。

**だが、基本的に変数名に日本語を使用することはない**

そもそもコンピュータと日本語の相性はあまり良くなく、
文字コード関連で余計なエラーを招く可能性があるので、
日本語じゃなきゃだめという強い理由がないと変数名に採用するのは、
避けるべきだ。

数字に関しては、先頭以外であれば、
変数名に含めても問題ない。

記号系に関しては、基本的にNGだが、
_とかは比較的よく使われる。


変数名の良い例
```
const greeting = 'hello'
const uriage1 = 10000
const kyouno_uriage = 1000
```

変数名の悪い例
```
const あいさつ = 'hello' //エラーにはならない
const 1uriage = 1000
const if = 1999 //予約語を変数名にしている
const kyouno uriage = 1000 //変数名に空白が入っている
```

# 変数に型を与える
さて、上記までの話は、
TypeScriptというより、
JavaScript寄りの話だったが、
TypeScriptの特徴はなんといっても、型にある。

変数にも型注釈を加えて書く。


```:index.ts
const greet: string = 'hello'
```

上記の: stringの部分が型注釈にあたる。

stringというのは、文字列のことで、
変数greetに代入されているのは、
'hello'という文字列だ。

なので、この場合は問題ないコードとなる。

**const greet: stringと書いた時点で、
greetという変数にはstring型しかいれることができないというのが、
上記のコードの意味である。**

試しにstring型以外を入れてみる。
```:index.ts
const greet: string = 100
```

すると、
```:errorメッセージ
Type 'number' is not assignable to type 'string'.
```

となる。

これは、100がnumber型なのに対し、
greetという変数がstring型になっているので、
型が一致しないよというコンパイルエラーである。

# 型の恩恵
先程変数は箱と言ったように、
まさしく、変数は処理されたあとの値を待ち受ける箱のように使うことがある。

その際、JavaScriptだと、型を宣言することはできないので、
箱は渡された値をそのまま入れるしかない。

**イメージとしては、毒を渡されても、
それが毒ですとは教えてくれず、黙って箱の中にしまってしまうのが、
JavaScriptだ。**

それに対して、TypeScriptは待ち受ける箱に予め型をつけることができるので、
渡されてきた値が型と違っていれば、違うよというコンパイルエラーを出してくれる。

**すなわち、毒を渡されても、
それが毒です、受け付けられませんとエラーを出してくれるのが、
TypeScriptだ。**

コンパイルエラーと言われると身構えてしまうが、
要は不適切な値を事前に弾いてくれているため、
非常にありがたい代物である。

JavaScriptとかだと、毒が全身に回って、死亡するまで
(ソフトウェア的には、バグが複雑化して手がつけられなくなるまで)
気づかない恐ろしさがあるともいえるのだ。

**まあ、何が言いたかったのかというと、
とりあえず、コンパイルエラーは喜ぼうっていうことである。**

# letとconst

上記までの具体例では、
変数宣言の際、基本的にconstを使用してきた。


これに加えて、letというものもある。

```:index.ts
let greet: string = 'hello'
```

書き方は、constの部分をletに置き換えるだけだ。


**letとconstの違いは再代入可能かどうかだ**

```:index.ts
const hello = 'hello'
hello = 'namasute' //Cannot assign to 'hello' because it is a constant.というエラーにな

let greet = 'hello'
greet = 'namasute' //エラーなし
console.log(greet) // namasuteと表示される
```


**再代入できるletの方が柔軟で良さげと思うかもしれませんが、
可能な限りletを使うのは避けるべきです。**

なぜなら、再代入可能ということは、
最初に宣言された値とは変わる可能性があるからだ。

つまり、letで宣言された変数の場合、
いま現時点でletの変数になんの値が入っているのか正しい状態なのかを
判断しなければならない。

```
let greet = 'hello'
greet = 'hello1'
let greet1 = 'hello1'
greet = 'hello'
greet1 = 'hello'
greet = greet1
greet = greet  + greet1
greet = greet + greet
console.log(greet)
```

実際には、こんなコードは嫌がらせのとき以外は書かないが、
文法上は、こういうコードも許してしまうということになる。

console.logで何が出力されるのか、
いちいち処理を追って行かないとよくわからない。

**つまり、letの使用は読み手に負担を与える可能性があるということだ**

そのため、ifやforなどの複雑なロジックで、
やむをえずletを使うしかない場面以外は基本はletを使わないようにするべきだ。

letで書いてしまったら、なんとかしてconstに書き換えできないか、
コードを見直すサインともいえるかもしれない。