Try   HackMD

W_TypeScript 個人筆記

TS 簡易基礎

  • TypeScript 只會進行靜態檢查,如果發現有錯誤,編譯的時候就會報錯。

基礎

聯合型別

一般來說 ts 的變數宣告只能接受一個特定的值,但如果我給變數設定兩個可接收的型別,那就可以接收兩個型別,下方範例可以看到有兩個型別並且用|分割

let myFavoriteNumber: string | number; myFavoriteNumber = 'seven'; myFavoriteNumber = 7;

抽象與介面

這兩個是 TS 才有的語法,可以想像是只 JS 的類,只是再把它拆分更加嚴謹

抽象 abstract

  • 建立一個抽象類別,定義函式但沒有具體公用,通常 value 是 void
  • void 代表著子類要自己實做方法,簡單來說就是空的,子類自己定義內容
  • 當子類要繼承它,就嚴格規定要使用祖先的函式,並且只能繼承一個方法
  • 不能直接 new 祖先類(父類),但子可以
  • 可以使用共用邏輯,比如
    • move() {
      console.log(${this.name} is moving.);
      }
abstract class Animal { abstract makeSound(): void; } class Dog extends Animal { makeSound() { console.log("Woof!"); } }

介面 interface

  • 建立一個合約,如果子類要繼承它,需要將裡面的屬性與方法一併繼承
  • interface 可以 extened interface,這樣子類可以一次繼承到兩個方法
  • 子可以繼承多interface
//interface 可以 extened interface,這樣子類可以一次繼承到兩個方法 interface Animal { name: string; } interface Dog extends Animal { bark(): void; } const pet: Dog = { name: "Barky", bark() { console.log("Woof!"); } };

變數、引數須強制加上型別

//這是ts寫法 let number: number = 25; //如果要讓變數有自由度可以加上 :any 或是為空 let number: any = 25; let number; //fnc 的變數需要強制加上型別,讓引數必須為此型別 function name(person:string){ console.log(`this name is ${person}`) }

物件型別

在 Ts 裡面,是用 interfaces 來定義物件型別,下面例子展示作法

//設定強制規則,之後使用都要按造此規則,否則將會抱錯 interface Person { name:string age:number } //正常使用 let tom:Person{ name: "tom" age:25 } //不正常,少一項 let tom:Person{ name: "tom" } //不正常,多了一項 interface 沒有的東西 let tom:Person{ name: "tom" age:25 gender:male } //////////////////////////// //可以看到 age 後方多了一個問號,這代表屬性非強制繼承 interface Person{ name:string age?:name } // 正常,雖然少了一項,但不會抱錯,因為 ? 表示可選擇使用 let tom:Person{ name: "tom" } //////////////////////////// //在規則裡新增一項可選擇性增加的屬性 interface Person{ name:string age?:name //首先[]裡代表屬性名稱是字串,再來就是接收值可以是任意 [propName:sting]:any } // 正常,雖然少了一項,但不會抱錯,因為 ? 表示可選擇使用 let tom:Person{ name: "tom" age:25 gender:male } ////////////////////////////\ //唯讀,不能賦值 interdace Person{ readonly id: number } //這會錯誤 let tom:Person{ } tom.id = 1

陣列型別

其實道理跟物件差不多

let sum:number[] = [1,2,3,4,5] //不正常,不能有字串的出現ㄑ let sum:number[] = [1,"2",3,4,5]

泛型

在 TypeScript 中,函式或變數都需要明確指定型別(如 string、number 等),這叫做強型別(strong typing)。當你希望程式更有彈性與重用性,可以根據「實際傳入的值」自動決定型別,就可以使用 泛型(Generic)。

  • 泛型的語法是 <T>,它會在使用時根據實際傳入的值,自動推斷或手動指定型別,

  • <T> 是介於 any(完全沒限制)與明確型別(如 string)之間的「彈性型別」。

  • <T> 的T是標示符,T可以自己定義名稱,只要有<>就是泛型,一般來說有會有代表的意思

常用名稱 含義說明
T Type,最常見的泛型名稱
U, V 當有多個型別參數時常用第二、第三個名
K Key,常用於鍵的泛型
V Value,常用於值的泛型
E Element,用於集合元素
TData 更語意化的寫法,例如 TData, TResult

泛型疑問

  • 泛型是甚麼
    • 所以依照範例 log<string>('Hello') 是指說檢查log()裡面的內容是否為字串,哪我是否可以寫成 console.log("hello"):string,還是規則就是要<>
  • <T>是甚麼,依照範例,可以任意賦值近陣列中嗎
    • 所以如果寫<T>就表示一樣也是要強制型別,但是依照傳入的值來定義,比如log<string>('Hello'),這就是我要定義這個log是字串,而引述也要強制寫成字串,是這個意思嗎,
    • <T> 不像 :string :number 那樣的寫死,也不像 :any 的隨意,我這樣理解正確嗎
    • 如果還不確定要傳入甚麼強制的值,就可以用<T>
  • 你說彈性擴充,那跟 any 差異?