---
# System prepended metadata

title: typescript 筆記

---


---
# typescript 筆記
##  前言

- 一個基於 JavaScript 的超集合（SuperSet）
- 提供型別系統（Type System），能夠在開發時期宣告型別
- 支援 ECMAScript，可將 TS 檔編譯成 JS 檔給瀏覽器解讀
## 型別系統 Type System
由於javescript是弱型別語言,typescript的出現就是要解決這個問題

typescript就是javascript的延伸其支援ECMAScript規範所以可以支援js代碼

**舉例typescript與javascript差異 :**

原生javascript :

![](https://i.imgur.com/RhMczog.png)

typescript :

![](https://i.imgur.com/TRbOPU4.png)

以上的範例可以看出typescript是如何註記型別，typescript的原始型別有以下幾種 ：

### Boolean
使用 boolean 定義布林值型別 :
``` typescript=
let isToggle:boolean = false 
```

注意：使用建構函式 Boolean 建立的物件不是布林值：
``` typescript=
let isToggle:boolean = new Boolean(１) 
```
直接呼叫Boolean返回的是一個boolean型別 ：

``` typescript=
let isToggle:boolean = new Boolean(１) 
```

在typescipt中，boolean是基本型別，而Boolean是建構函式


### String
使用 String 定義字串型別 :
``` typescript=
let myName:string = "Danny" 
```

typescript 支援樣本字串：
``` typescript=
let age:number = 10
let myName:string = 'Danny'
let sentense = `Hellow my Name is ${myName} my age is ${age}`
```
使用樣本字串創建type：
``` typescript=
type Direction = 'row'|'column'
type Position = 'center'|'right'|'left'
type PositionVarants = `${Position} - ${Position}`
```
型別推論結果是 ：

![](https://i.imgur.com/mbZrPP2.png)

註 ： typescript會透過樣本字串結合新型別

### Number
使用 Number 定義字串型別 :
``` typescript=
let decLiteral: number = 6;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;
```

### 空值
在typescrupt可以透過void，表示沒有返回任何值的函式:
``` typescript=
function sayHellow():void{
    console.log('Hellow world')
}
```

### Null 和 Undefined
使用 **null** 和 **undefined** 來定義這兩個原始資料型別:
``` typescript=
let u: undefined = undefined;
let n: null = null;
```

undefined 和 null 是所有型別的子型別。也就是說 undefined 型別的變數，可以賦值給 number 型別的變數:
``` typescript=
let num:number = undefined
```
### 陣列
使用 []定義原始型別集合:
``` typescript=
let animals:string[]=['lion','pig']

let peopleNo:number[]=[10,5]
```

### 任意值
賦予變數任何型別:
``` typescript=
let addressNO:any=281
```

### 列舉型別 enum
以下為例 :
``` typescript=
enum Color {Red,Green,Blue}//output : 0,1,2
let c:Color =Color.Green //1
```
編譯結果：
``` typescript = 
var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Green"] = 1] = "Green";
    Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));

```
可以看到enum的概念是一個object，值＝鍵，鍵＝值

## 型別推論（Type Inference）

>TypeScript會依據型別規則推導出一個資料型別

以下方程式碼為例：
```typescript＝
let myLuckyNumber = 12
```

等同於上方：
```typescript＝
let myLuckyNumber：number = 12
```

如經過TS型別推論後的變數，再指定其他值會報錯：
```typescript＝
let myLuckyNumber：number = 12
myLuckyNumber = '7'

// index.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.
```
### e.g.自動註記
![](https://i.imgur.com/0H4fk4B.png)
```
message變數就被推論為string
```

## 型別斷言 Type Assertion

> 當最後需要改變變數型別時，為了避免出現警告錯誤，這個機制就是『型別斷言』

型別斷言有兩種寫法
- 第一種 ：`<型別值>`
``` typescript＝
let code: any = 'Hello'; 
let helloCode = <string> code;
```

- 第二種 ：`值as型別`
``` typescript＝
let code: any = 'Hello'; 
let helloCode =code as string;
```
## Utility Types
### Required<Type>
簡單舉個Utility Types例子 ：
```typescript=
interface Props {
  a?: number;
  b?: string;
}
const obj2:Required<Props>={
    a:5
}
//obj2會報錯因為b已經不是可選項的屬性
```
Required<Type>是typescript原生的type可以讓型別中的可選項變成reuired
[更多範例 ...](https://www.typescriptlang.org/docs/handbook/utility-types.html)
## interface vs type

## 相同點
### type
```typescript=
type User={
    name:string
    age:number
}
let user:User={
    name:'Danny',
    age:20
}
```
以上我們定義一個型別User他有name、age兩個，透過user指定User型別告訴蓋變數有name、age以及其對應的型別

### interface
```typescript=
interface User={
    name:string
    age:number
}
let user:User={
    name:'Danny',
    age:20
}
```
註 ：與type寫法類似但對typescript來說是不同的解釋，type是個型別用引而interface是產生一個新型別，interface算是一個介面的延伸如class一樣介面可以extend屬性但type不能，如以下例子 ：

## 不同點
### overwrite
```typescript=
interface info {
    personName:string
}
interface info  {
    addressNo:number
}
    
```
介面info可以透過複寫的方式延伸型別
### extend
```typescript=
interface Mailable {
    send(email: string): boolean
    queue(email: string): boolean
}
interface FutureMailable extends Mailable {
    later(email: string, after: number): boolean
}
    
```
註 ：以上的FutureMailable就是一個繼承的概念，FutureMailable擁有Mailable的屬性同時增加later函式的方法

### 一個class可以繼承多個屬性
```typescript=
interface Mailable {
    send(email: string): boolean
    queue(email: string): boolean
}
interface FutureMailable   {
    later(email: string, after: number): boolean
}

class Mail implements FutureMailable,Mailable {
    later(email: string, after: number): boolean {
        console.log(`Send email to ${email} in ${after} ms.`);
        return true;
    }
    send(email: string): boolean {
        console.log(`Sent email to ${email} after ${after} ms. `);
        return true;
    }
    queue(email: string): boolean {
        console.log(`Queue an email to ${email}.`);
        return true;
    }
}
    
```
以上敘FutureMailable為例，在class中使用interface去繼承型別使用的關鍵字是implements，如需使用多個介面只要在後面新增就好。

## Mixins
<T>為typescript optional type的方法，只需要再函數括號前新增就好
```typescript=
function base<T>() {
  class Base {
    static prop: T;
  }
  return Base;
}
function derivedg<T>(){
  class Derived extends base<T>() {
    static anotherProps:T
  }
  return Derived
}
class Spec extends derivedg<string>(){}
Spec.anotherProps//string
Spec.prop//string
```
上述是一個class的mixins設定，derived函數是繼承Base函數的方法，class Spec可以繼承derived回敷函數的調用結果讓Spec繼承class Base、Derived，也因為optional type的關係Spec.anotherProps的型別結果是String

## typescript 編譯設定
全局安裝typescript
```
npm install typescript -g
```
mac 安裝全域套件記得加sudo
```
sudo npm install typescript -g
```


初始化ts專案
```
tsc --init
```
專案中會跑出tsconfig.json這支檔案
![](https://i.imgur.com/saMVbvf.png)

註 ：tsconfig.json為ts編譯的設定檔案

例如outDir就是要檔案編譯後要放的資料夾
![](https://i.imgur.com/fuUTqlg.png)

    typescript很貼心在tsconfig.json中每一個option都有解釋說明用法非常直觀。

### 小結

儘管javascript自由度很高，但在型別使用上卻有缺陷，時常搞不清楚api呼叫後的結果是什麼，typescript的出現就是要補足這個問題，typescript的主要概念有兩個，其一Type Inference，自動推倒變數結果防止變數型別錯亂，其二就是Type Assertion，當一個變數可能會有多個以上的型別時，就可以夠過斷言決定變數想要的結果為何，也算是typescript提供的自由度。12
   