# TypeScript - Type

#### 學習資源：

[Codecademy](https://www.codecademy.com/enrolled/courses/learn-typescript)

---

## Type Inferences 型別推論

在 JavaScript 中我們可以對變數進行任意賦值，這樣的方式很彈性也可以很快地 coding。但也因為如此的彈性，才會造成許多意外的 bug。

所以在 TypeScript 中，我們首先會發現的是，當你賦值給一個變數後，你將沒辦法再賦值其他型別的值給這個變數。這是型別推論中的一個例子，TypeScript 會希望變數的型別跟最一開始被賦值的型別要一樣。

TypeScript 可以識別 JavaScript 的 primitive 型別：

- boolean
- number
- null
- string
- undefined

若我們嘗試對一個變數重新賦值一個不同的型別，TypeScript 會顯示錯誤。

```typescript
let order = 'first';

order = 1;
```

當執行以上的程式碼，TypeScript 會顯示下列的錯誤：

`Type 'number' is not assignable to type 'string'`.

也就是 TypeScript 的型別系統告訴我們說，他會希望 `order` 的型別要跟一開始一樣是 `string` 才可以，要不然就會顯示錯誤。

而只要我們也把重新賦值的值也改成string 就可以解決了。

```typescript
let order = 'first';

order = '1';
```

## Type Shapes

因為 TypeScript 已經知道我們變數的型別，他也會知道這個變數會包含哪一些屬性或方法。

這點在 JavaScript 中的內建型別都存在已知的屬性和方法。例如，已知所有字串都具有 `.length` 屬性和 `.toLowerCase()` 方法。

```typescript
"OH".length; // 2
"MY".toLowerCase(); // "my"
```

所以當你引用錯誤的方法時，TypeScript 就會提醒你可能錯了。

```typescript
"MY".toLowercase();
// Property 'toLowercase' does not exist on type '"MY"'.
// Did you mean 'toLowerCase'?
```

## Any 型別

在一些地方，TypeScript不會試圖推斷某變數是什麼型別——這種情況通常是在沒有 assign 初始值的情況下宣告變數。 在無法推斷型別的情況下，TypeScript 會考慮將變數設為 `any` 型別。

型別 `any` 的變數可以 assign 給任何值，如果稍後重新 assign 給其他型別，TypeScript 也不會給出錯誤。

```typescript
let onOrOff;

onOrOff = 1;
onOrOff = false;
```

## Variable Type Annotations 型別註釋

在某些情況下，我們希望宣告一個沒有初始值的變數，同時仍然確保它在未來會被 assign 到某種型別的值。 如果只用 `any` 型別，TypeScript 將無法起到監督 assign 變數的作用。

所以我們可以透過使用型別註釋來告訴TypeScript某變數是什麼型別或將是什麼型別。

變數可以在名稱後面新增型別註釋（也稱為型別宣告）。透過加上帶有冒號（:）和型別（例如數字、字串或任何）的變數來做型別註釋。

```typescript
let mustBeAString : string;
mustBeAString = 'Catdog';

mustBeAString = 1337;
// Error: Type 'number' is not assignable to type 'string'
```

在上面的程式中，我們明確宣告 `mustBeAString` 為 `string` 型別，而不給它 assign 初始值。 這使我們能夠 assign 值 `“Catdog”`，但當我們後來嘗試給它分配一個 `number` 時，TypeScript 會給我們一個錯誤訊息，告訴我們 `number` 被錯誤地分配給 `string` 型別的變數。

型別註釋的語法在編譯到JavaScript時，它們會自動被刪除。


