小白Pai
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Typescript 型別與介面 ###### tags: `Typescript` ## 壹、前線維護・型別推論 X 註記 - Type Inference & Annotation ### 一、 基礎型別(Types) ![](https://i.imgur.com/qsxPANb.png) - **原始型別 Primitive Types** 包含 **number**, **string**, **boolean**, **undefined**, **null**, ES6 介紹的 **symbol** 與時常會在函式型別裡看到的 **void** - **物件型別 Object Types** 但我個人還會再細分成小類別,但這些型別的共同特徵是 —— 從原始型別或物件型別組合出來的複合型態(比如物件裡面的 Key-Value 個別是 string 和 number 型別組合成的): - 基礎物件型別:包含 JSON 物件,陣列(Array<T>或T[]),類別以及類別產出的物件(也就是 Class 以及藉由 Class new 出來的 Instance) - TypeScript 擴充型別:即 Enum 與 Tuple,內建在 TypeScript - 函式型別 Function Types:類似於 (input) => (Ouput) 這種格式的型別,後面會再多做說明 - **明文型別 Literal Type** 一個值本身也可以成為一個型別,比如字串 "Hello world" —— 若成為某變數的型別的話,它只能存剛好等於"Hello world"` 字串值;但通常會看到的是 Object Literal Type,後面也會再多做說明 - **特殊型別** 筆者自行分類的型別,即 any、never(TS 2.0釋出)以及最新的 unknown 型別(TS 3.0釋出),讀者可能覺得莫名其妙,不過這些型別的存在仍然有它的意義,而且很重要,陷阱總是出現在不理解這些特殊型別的特性 - **複合型別** 筆者自行分類的型別,即 union 與 intersection 的型別組合,但是跟其他的型別的差別在於:這類型的型別都是由邏輯運算子組成,分別為 | 與 & - **通用型別** Generic Types:留待進階的 TypeScript 文章介紹,一種讓程式碼可以變得更加通用的絕招 ### 二、型別推論在原始型的運作 #### 1.型別推論 - TS 除了認得定義過後的變數外,也認得該變數型別是 Boolean,這個辨識推論型別的行為就是所謂的**型別推論**(Type Inference) ![](https://i.imgur.com/vCieknt.png) #### 2.Nullable Types - 但如果對 nothing 或 nothingLiterally 這兩個型別作確認的話,結果 TypeScript 會把它們推論成 any 型別,因為 null 或 undefined 被稱為 **Nullable Types**,被認為是 any 型別 ![](https://i.imgur.com/rIRg04U.png) - Nullable Types 會被認為是 any 型別,因此可以被指定為任何型態 ![](https://i.imgur.com/2ll0HA3.png) #### 3. TDZ (Temporal Dead Zone,暫時性死區) - 宣告一個變數後,在還沒指派值之前,用另外一個變數去接他,這時 TS 就會提出質疑。 ![](https://i.imgur.com/XIiIk7S.png) - 在未確定變數被正式丟入合法的值之前的這段空間,不能使用該變數。 ![](https://i.imgur.com/igX7Xnd.png) #### 4. 對遲滯性指派進行型別註記 ```javascript= let A: type; A = B as type; ``` ## 貳、物件型別 X 完整性理論 - Object Types Basics ![](https://i.imgur.com/08H3R5u.png) ### 一、基礎物件型別 #### 1. **JSON 物件格式** TS 會提醒你推論後的型別是什麼 ![](https://i.imgur.com/3r149DA.png) 就算是 nullable 和 undefine 的型別也會出來,而不是 any ![](https://i.imgur.com/xrl21Bq.png) #### 2. 型別覆蓋的例子 ```javascript= let info = { name: 'Maxwell', age: 20, hasPet: false, } let something = { null: null, define: undefined, } ``` - **屬性值被錯誤的型別插入/覆寫干擾** 型別錯誤,TS 會主動給予提示 ![](https://i.imgur.com/DOhVlcH.png) - **物件分別被正確或者是錯誤的物件格式整體複寫** 多一個鍵或少一個鍵都不行 ![](https://i.imgur.com/zCrOQEE.png) - 型別推導時就會把整個物件,包括 key-value 的型別都作定義 ![](https://i.imgur.com/NEWX9mj.png) - 主動註記物件型別時,會被標記為物件型別,因此只要是物件型別就可以付與值給它 ![](https://i.imgur.com/IsrNrna.png) - **直接對物件新增值** 新增或減少值會引起 TS 的警告 ![](https://i.imgur.com/rRlCR0A.png) - 結論 - 對物件內的屬性覆寫,其值的型別必須相等 - 對整個物件覆寫,格式必須完全相等 - 用以下三種形式新增物件是允許的 ```javascript= let nestedObject = { prop: 'Hello', child: { prop1: 12, prop2: false, } } let obj1 = {hello: 'world'} let obj2 = {...obj1, goodbye: 'Cruel world'} let obj3 = {hello: 'Another World'} let obj4 = Object.assign(obj3, { goodbye: 'Cruel World' }) ``` ### 二. 定義物件 let justAnObject1 = { hello: 'World' } let justAnObject2: object = { hello: 'World' } 定義物件的時候這兩種寫法, 1. **沒有主動註記物件型別**,第一個可以改寫裡面的hello的值 justAnObject1.hello = ‘WW’ 2. **主動註記物件型別**,第二個則是要**整個物件覆蓋掉**,然後連key值都可以改 = justAnObject = { goodbye: 'Cruel world', kk: 'Another'} 因為 TS 認為object 型別指的是任何 JS 物件(儘管格式不同)都可以被套入,但是不允許對該物件做細部微調 - 物件狹義的定義 典型的 {} 這種東西的寫法 - 物件廣義物件的定義 包含 JSON 格式的物件、陣列、函式、類別、類別創建出之物件 #### 1. 將狹義物件用廣義物件覆蓋 實驗證實,在物件主動標記型別的狀態下,廣義定義的物件是可以覆蓋的 ![](https://i.imgur.com/GXu6Kur.png) #### 2. 將廣義物件用狹義物件覆蓋 ![](https://i.imgur.com/tksmPKw.png) **廣義物件在被 TypeScript 推論的狀態下,屬性不能被任意新增或更改成其他型別** 能夠做的事情只有: - 全面覆寫,廣義物件的屬性對照型別格式也要完全對位 - 更改廣義物件本身就擁有屬性對應的值,其中:要帶入的值的型態必須對應到該屬性的型態 ## 參、函式型別 X 積極註記 - Function Types ![](https://i.imgur.com/jmqUjoh.png) ### 1. 函式註記- 函數參數 函數參數如果不標記爲何種型別,他只能是 any,如果 TS 不管輸入參數的型別。像下面的函式就會變成字串型別+數字型別 ```javascript= let addition = function(paras1, paras2) { return paras1 + paras2 } addition(1, '2') ``` 因此必須在函數的參數上加上型別 ```javascript= let addition = function(paras1: number, paras2: number) { return paras1 + paras2 } addition(1, 2) ``` ### 1. 函式註記-函式輸出的註記 在輸入型別確認後,TS 會自動幫我們推導出輸出型別為何 ![](https://i.imgur.com/TUlWQNx.png) 也可以自行註記型別 ![](https://i.imgur.com/G3C6FNH.png) - 如果輸出的型別為 any 該如何註記? ![](https://i.imgur.com/H8JjSDt.png) - 我們儘量不要讓變數被推導為 any 的型態。 ![](https://i.imgur.com/lNcZAEx.png) - 函式不回傳值的狀態 void ![](https://i.imgur.com/SH8dtqO.png) - 驗證小實驗 - 只有定義回傳為 undefine 時,卻沒回傳值,TS檢查不會通過 ![](https://i.imgur.com/U3ktTPK.png) ## 肆、陣列型別 X 型別陣列 - Array Types ![](https://i.imgur.com/u1M6H7u.png) ### 1.陣列型別 Array Types - 單一陣列型別 TypeScript 會按照開發者認為的邏輯,把這種元素(Element)皆為同型別 T 的陣列用 T[] 的方式表示。 ![](https://i.imgur.com/WAQ0KMO.png) - 混合陣列型別 ![](https://i.imgur.com/gnhsyO5.png) - 函式陣列型別 ![](https://i.imgur.com/YDi8aVj.png) - 一個陣列中擁有不同種類的型別 ![](https://i.imgur.com/Xp5dLtJ.png) ![](https://i.imgur.com/uEzHhkA.png) - 陣列中物件擁有不一致數量的屬性 ![](https://i.imgur.com/ALjFEuZ.png) ### 2. 定義變數的型別 如果要在陣列中加上一個 null,就得再定義陣列時使用 union 允許 null ![](https://i.imgur.com/TZsoBow.png) ## 肆、前線維護・陣列與函式 X 陣列與元組 - Array & Functions & Tuples ![](https://i.imgur.com/ZaiYaLN.png) ### 一、回呼函數 回呼函數一般情況下 TS 會幫你註記 ![](https://i.imgur.com/tugbCar.png) ### 二、陣列與元組 Arrays & Tuples - 相對於型別註記(string|Date)[],我們只知道陣列中有這兩個型別,但不能指定哪個位置必須放哪個型別。 因此 TS 用元組來做註記 ![](https://i.imgur.com/tVkF4Vd.png) - 運用型別化名註記元組型別 ![](https://i.imgur.com/faTj4yf.png) - 元組與陣列表示法 ![](https://i.imgur.com/6tTv0fV.png) - 不過元組的缺點就是:型別等同的兩個元素,儘管型別上是正確的,但是資料的意義上是不同的,就算被顛倒,TypeScript 也因為只會比對型別而不會進行警告 ![](https://i.imgur.com/MmDUG4u.png) 通常會建議資料儘量用 JSON 物件格式表示 ![](https://i.imgur.com/4Au3XwN.png) ## 伍、前線維護・列舉型別 X 主觀列舉 - Enumerated Types ![](https://i.imgur.com/YixmmhK.png) ### 一、列舉(Enumerate) 把變數的範圍限制在某些限制下進行存取並賦予其定義 - 一串東西的集合 - 同時具備**主觀上強烈的共通性(Similarity)**及**獨有特質(Uniqueness)** Ex: 星期幾、上下左右、交通工具... - 定義列舉時不需等號 ```typescript= enum WeekDay { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } ``` - ts 將上面這段程式碼編譯的結果 ```javascript= var WeekDay; (function (WeekDay) { WeekDay["Sunday"] = "Sun"; WeekDay["Monday"] = "Mon"; WeekDay["Tuesday"] = "Tue"; WeekDay["Wednesday"] = "Wed"; WeekDay["Thursday"] = "Thu"; WeekDay["Friday"] = "Fri"; WeekDay["Saturday"] = "Sat"; })(WeekDay || (WeekDay = {})); ``` - 取用 WeekDay 的值會是 Enum -> ```typescript= let TGIF = WeekDay.Sunday console.log(TGIF) // TGIF 為 enum let Sunday = WeekDay[TGIF] console.log(Sunday); // Sunday 為 string 型別 ``` - 指向字串用法 ```typescript= enum Week { Sunday = "Sun", Monday = "Mon", Tuesday = "Tue", Wednesday = "Wed", Thursday = "Thu", Friday = "Fri", Saturday = "Sat" } // 編譯結果 ===> var Week; (function (Week) { Week["Sunday"] = "Sun"; Week["Monday"] = "Mon"; Week["Tuesday"] = "Tue"; Week["Wednesday"] = "Wed"; Week["Thursday"] = "Thu"; Week["Friday"] = "Fri"; Week["Saturday"] = "Sat"; })(Week || (Week = {})); ``` - 指向數字,自動遞增 ```typescript= enum JobGrade{ JuniorE8 = 8, JuniorE9, SeniorE10, SeniorE11, Other = 0, Guest } // 編譯結果 ===> var JobGrade; (function (JobGrade) { JobGrade[JobGrade["JuniorE8"] = 8] = "JuniorE8"; JobGrade[JobGrade["JuniorE9"] = 9] = "JuniorE9"; JobGrade[JobGrade["SeniorE10"] = 10] = "SeniorE10"; JobGrade[JobGrade["SeniorE11"] = 11] = "SeniorE11"; JobGrade[JobGrade["Other"] = 0] = "Other"; JobGrade[JobGrade["Guest"] = 1] = "Guest"; })(JobGrade || (JobGrade = {})); ``` ## 陸、明文型別 X 格式為王 - Literal Types ![](https://i.imgur.com/sSiAehP.png) 只要是表達廣義物件的格式或者是任意型別(包含原始型別的)複合組合(union 與 intersection 也算在內就隸屬於明文型別的範疇。 ![](https://i.imgur.com/N65oyYE.png) ![](https://i.imgur.com/VuQ6OYz.png) ### 一、型別化名 Type Alias 型別化名的主要目的為簡化程式碼以及進行型別的抽象化(Type Abstraction) ```typescript= // 原本的型別太過複雜 let powerOp: (n1: number, n2: number) => number = (n1: number, n2: number) => { return n1 ** n2 } // 加上 Type Alias 進行簡化 type MathOperator = (n1: number, n2: number) => number let powerOpTypeAlias: MathOperator = (n1: number, n2: number) => n1 ** n2 ``` - 函式型別的化名 任何變數 A 被型別化名 U 註記,則該變數被指派到的函式值,不需要積極註記,因為早在定義化名的時候,這個步驟就被做掉了 => 函式型別不用積極註記的第二種情況 ![](https://i.imgur.com/ETxZdeu.png) - 廣義物件的積極註記 ```typescript= type PersonInfo = { name: string, age: number, hasPet: boolean } function printInfo(info: PersonInfo) { console.log(info.name) console.log(info.age); console.log(info.hasPet); } printInfo({ name: 'Martin', age: 28, hasPet: false, hello: 'John', // ts 提示錯誤 nothingSpecial: null, }) ``` 如果再變數裡的物件,只要明文型別有符合,不要減少,就算多出鍵值對也能通過TS 因此**任何變數需要存取廣義物件時,必須進行積極註記型別的動作。** ```typescript= let infoAboutMartin = { name: 'Martin', age: 28, hasPet: false, hello: 'John', nothingSpecial: null, } printInfo(infoAboutMartin) // 通過TS ``` ## 柒、選用屬性 X 型別擴展 - Optional Properties ![](https://i.imgur.com/R0GBJeb.png) ### 一、 使用<prop>?選用屬性註記 當物件內的屬性,不是必須出現的狀況,可以使用 Optional Properties ![](https://i.imgur.com/tC5WUgX.png) - 若某屬性 P 屬於某物件的明文型別 的屬性之一,且該屬性對應的型別值為 T,而 A 是該明文型別的別名,則: ``` type A = { P?: T }; ``` 代表: 1. 選擇性地忽略 P 這個屬性。 2. 因為推論出來的結果會是以下的形式,因此也可以選擇寫出 P 屬性但填入 undefined 這個值: ``` { P?: T | undefined } ``` ### 二、複合類別 ![](https://i.imgur.com/rUzkxnz.png) ### 三、元組型別的選用元素 ![](https://i.imgur.com/pjxdxpQ.png) ## 捌、特殊型別 - Never Type ![](https://i.imgur.com/esKA2xp.png) - 無法跳脫出該函式或方法 - 出現例外結果中斷執行 - never 型別為所有型別的 subtype ![](https://i.imgur.com/rK16cKS.png) ## 玖、特殊型別 - Any 真的非不得已狀態下或者是快速測試下,可以使用 any。不過開發上,儘量不要用到 any 比較好;或者真不巧,遇到 any,也應當主動註記。 ### 一、出現時機 - **遲滯性指派 Delayed Iniitialization**:變數定義時,除了未加註記(Type Annotation)外,也沒有指派值或者被指派為 Nullable Types。 - **一般宣告下的函式參數**:一般被宣告的函式,其參數通常會直接被推論為 any,又被稱作 Implicit any 的情形。此狀況是少數會被 TypeScript 主動通報的 - **函式回傳之值**:有些實務上,型別無法確定,因此到最後只能將回傳值預設為 any(如:JSON.parse) - **未註記之空陣列**:沒有積極型別註記到的空陣列,其預設推論為 any[] - **跟 I/O 行為有關**:例如,從外部 CSV 檔案讀取表格行格式(通常用陣列或元組型別),若沒有特殊註記的話,通常會用 any 作表示 ## 拾、特殊型別 - Unknown Type ![](https://i.imgur.com/ECHf28n.png) > unknown 相對 any 來說,是一種更安全的型別機制 ### 1. unknown 的可以與不可以 - 只要當變數被註記為 any 或 unknown,該變數照樣都可以接收任意型別的值。 ![](https://i.imgur.com/JdYuDx8.png) - unknown 型別的值不能被強行指派到除了 any 或 unknown 型別外的任意型別變數 ![](https://i.imgur.com/8ulSEf7.jpg) ![](https://i.imgur.com/HMQTfpW.png) ![](https://i.imgur.com/IAQke4d.png) - 1. 只要程式根據判斷式與敘述式的結構,縮小變數在型別推論上的範疇,我們就可以讓純 unknown 型別的變數被指派到任意型別上 ![](https://i.imgur.com/P3R1rVY.png) - 2. 顯性的型別註記 ![](https://i.imgur.com/LzgwIT4.png) - 被標記為 unknown,不能呼叫任何方法或屬性,亦不可作為任何函式或方法之參數),any 型別不管亂呼叫什麼東西,都不會有事。 ![](https://i.imgur.com/JgaKxKX.png) ![](https://i.imgur.com/TOA0Iu1.png) - 若 unknown 變數被顯性地型別註記為某型別 T(其中 T 不為 unknown),則 unknown 變數可以作為該型別 T 之代表值,進行該型別底下合理之操作 ![](https://i.imgur.com/y1GlAoq.png) - 若 unknown 變數被控制流程限縮型別至某型別 T(其中 T 不為 unknown),則 unknown 變數可以作為該型別 T 之代表值,在該控制流程的範圍內進行合理之操作 ![](https://i.imgur.com/kdoM8N3.png) ### 2.寫一個安全的函式(或方法)把不安全的函式(或方法)包裝起來 把 JSON.parse 這種會回傳 any 的方法函式包裝起來。 ![](https://i.imgur.com/47vB9CK.png) ### 3. unknown 型別進行複合 type U = unknown & T => T type U = unknown | T => unknown type U = unknown | any => any ## 拾壹、型別化名 ![](https://i.imgur.com/0XPOvCI.png) 型別化名的意義就是把複雜格式(尤其是明文格式)的型別進行程式碼簡化與抽象化 ### 一、用法 若某型別 T, **T 可為任何的型別**: - **原始型別、 物件型別、 TypeScript 內建型別、 明文型別、 複合型別、 Generics 通用型別**等 其中我們想要讓該型別 T 等效於別名 A,則可以使用 TypeScript 的 type 關鍵字進行化名宣告: ``` type A = T ``` ![](https://i.imgur.com/U2zx3jt.png) ## 拾貳、介面宣告 X 使用介面 - TypeScript Interface Intro.. ![](https://i.imgur.com/aF3scLO.png) TypeScript Interface 可以藉由關鍵字 interface 宣告出來,介面裡面的詳細定義可為: - **物件格式**:即 JSON 格式,是為屬性對型別,不是對值 - **單一函式格式**:沒有任何屬性,就是函式而已,但不一定需要標上函式名稱 - **混合格式**:即『物件格式』與『單一函式格式』混合在一起 ![](https://i.imgur.com/OFxbQR6.png) ### 一、interface 檢查機制 - 多一鍵少一鍵都不行 ![](https://i.imgur.com/tJOwQw9.png) - 如果講物件帶入變數,再放進函式裡面,只要不少於 interface 定義的型別就不會出錯 ![](https://i.imgur.com/nKfF79P.png) - 為變數積極註記 ![](https://i.imgur.com/WyeQIzT.png) ### 二、interface 的介面擴展(Interface Extension / Inheritance) ![](https://i.imgur.com/pJr2DRL.png) - 多個介面要進行延伸,其中的兩個介面互不相容,就不能進行擴展的動作。 ![](https://i.imgur.com/ESPN3hi.png) ### 三、介面 Interface V.S. 型別 Type >- **介面(Interface)的意義** —— 跟規格的概念很像,可以擴充設計、組裝出更複雜的功能規格 > - **型別(Type)的意義** —— 代表靜態的資料型態,因此型別一但被定義出來則恆為固定的狀態。儘管可以利用型態的複合(intersection 與 union)看似達到型別擴展的感覺,然而這個行為並不叫作型別擴展,而是創造出新的靜態型別 - 介面使用上比較偏實作面,下面程式碼定義用戶帳號,而用戶帳號由"帳戶系統"和"帳戶個人資料"組成,藉由 interface 就可以把資料拆分的更細,讓管理程式變得輕鬆 ![](https://i.imgur.com/9yt5pVG.png) - interface 單字可以類比為 TypeScript 的介面,而 implementation 單字可以類比為型別系統裡的 type。 - 介面:規格(Spec)的概念,可以組裝、延展(使用 extends) - 型別:靜態的資料格式,不能被延展,每一次宣告新的型別化名 —— 對型別進行複合形式的操作 —— 都是在定義新的型別,不是延展作用 ## 拾参、函式超載 X 究極融合 - Function Overload & Interface Merging ![](https://i.imgur.com/ees1OnD.png)ㄋ功能多樣性 X 多樣性介面 - More on TypeScript Interface ### 一、函數超載 兼容不同情況函數輸入與輸出的型別註記 - 介面定義的屬性對應的函式可以- 進行超載的動作。 - 被超載的函式名稱必須相同。 - 若某物件實踐該介面時,必須符合該介面裡超載過的函式之所有情形 - 單純函式形式的介面也可以進行函式超載,差別在沒有名稱標記而已。 ![](https://i.imgur.com/GCeyRL1.png) ### 二、介面融合 - 若某介面 I 被重複定義多次,則該介面到最後的推論結果會是所有重複定義的介面的交集。 - I 若被重複定義時,裡面若干屬性跟過去所定義的某屬性相符的話,該屬性的型別必須跟過往定義出的介面裡的屬性之型別吻合。 ![](https://i.imgur.com/5x4S11V.png) - 整合第三方套件範例 ![](https://i.imgur.com/VgJbGnz.png) ## 拾肆、功能多樣性 X 多樣性介面 - More on TypeScript Interface ![](https://i.imgur.com/e0MpDGf.png) ### 一、Indexable Types - 模仿部分廣義物件的行為 indexable Types 在介面及型別都能使用 - 固定屬性的型別 - 對應 - 固定值的型別 ![](https://i.imgur.com/dWE9pv0.png) - Warning - 不能直接用陣列形式初始化值(除非是空陣列),由於陣列屬於 JS 物件的一種,而物件的屬性初始化時不允許為 string 以外的型態,因此初始化陣列的索引(index)都會以 '0', '1', '2' ... 這種字串的數字形式初始化,所以才會被 TypeScript 判定結果是錯誤! - 空陣列可以被初始化則是因為 TypeScript 認為都沒有屬性,沒有檢測之必要 - [index: number] 將索引部分鎖定在 number 型別上,目的是為了防止開發者呼叫字串型別的屬性(或是用點的方式呼叫屬性),而是模擬陣列的行為 -- 用數字來檢索該物件裡的內容 - 當物件必須在 [index: number] 這種狀態下初始化時,必須用 JSON 物件的格式,指定索引的位置(數值)並填入對應的值(當然,值必須符合型別 T,其中 T 為 [index: number]: T 裡面的 T) ``` [keyName: TKey]: TValue ``` - TKey 必須為 number 或者是 string 其中一種,不能為其他型別與 number 和 string 的複合格式(連 number | string 是不接受的!) - TValue 可為任意型別 ### 二、唯讀屬性 Readonly 在屬性前加入 readonly 的關鍵字,該屬性就會變成唯讀模式(Read-Only)。 ![](https://i.imgur.com/zluCbwf.png) ![](https://i.imgur.com/nhUw8Jn.png) ### 三、介面的混合格式 Hybrid Type Interface - 混合格式:即將『物件格式』跟『單一函式格式』混合在一起 ![](https://i.imgur.com/S96VdGQ.png) ![](https://i.imgur.com/jBm52xX.png) - 忘記實踐出混合型態介面裡的屬性與方法,TS 是不會檢查的 ## 拾伍、型別檢測 Type Guard - 控制流程分析 - 推論被限縮 ![](https://i.imgur.com/guBEngh.png) ![](https://i.imgur.com/hkkDCji.png) ### 一、行為限縮的技巧 - 若想要過濾出純原始型別的值的話,使用 typeof 操作子 - 若想要過濾出廣義物件型別的值的話,使用 instanceof 判斷操作子,並填上屬於該物件型別所屬的類別 - 其他方式,譬如 Array.isArray 可以檢測陣列

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully