欧洲精品久久久av无码电影,日日噜噜夜夜爽爽,精品无码国产自产拍在线观看蜜,人妻少妇被粗大爽9797pw,羞国产在线拍揄自揄视频,国产白嫩漂亮美女在线观看,天码欧美日本一道免费,av大片在线无码免费

      歡迎來(lái)到同城快修-附近家電維修、家電清洗、家電安裝服務(wù)平臺(tái)

      24小時(shí)家電維修熱線:

      400—1558638

      當(dāng)前位置:主頁(yè) > 洗衣機(jī) > 維修資訊 >

      【最全分析總結(jié)3W字】我是怎樣從0開始學(xué)會(huì)TypeScript的

      發(fā)布日期:2023-09-25 02:09:41 瀏覽:
      【最全分析總結(jié)3W字】我是怎樣從0開始學(xué)會(huì)TypeScript的 前言

      一邊學(xué)習(xí),一邊記錄,前前后后花了至少2個(gè)月的時(shí)間,算是把TS大部分都搞明白了。

      這篇文章的篇幅有點(diǎn)長(zhǎng),是我本人學(xué)習(xí)過(guò)程中的一些記錄,參考了很多優(yōu)秀博主的一些文章,以及在B站看了一些TS的視頻,把幾乎所有TS涵蓋到的基礎(chǔ)知識(shí)點(diǎn)都總結(jié)了下來(lái),所以,對(duì)于想學(xué)習(xí)TS的小伙伴下來(lái),一定一定要認(rèn)認(rèn)真真把這篇文章看完。

      3萬(wàn)字的教程,不敢說(shuō)是全網(wǎng)最好,但可以說(shuō)是全網(wǎng)最詳細(xì)。

      對(duì)于新手入門來(lái)說(shuō)是一篇非常不錯(cuò)的寶藏文章,幾乎每個(gè) TypeScript 的知識(shí)點(diǎn)都有詳細(xì)的講到,并且附上一些簡(jiǎn)單的示例,通俗易懂,希望可以給想學(xué)習(xí) TS 的小伙伴帶來(lái)動(dòng)力!

      一、了解TypeScript1. 什么是TypeScript
      • TypeScript是由微軟開發(fā)的一門開源的編程語(yǔ)言。
      • TypeScript,簡(jiǎn)稱TS,是JavaScript的超集(以JavaScript為基礎(chǔ)構(gòu)建的語(yǔ)言,JS有的TS都有)。
      • Typescript = Type + JavaScript(在JS基礎(chǔ)之上,為JS添加了類型支持)。
      • 可以在任何支持JavaScript的平臺(tái)中執(zhí)行。
      2. 為什么需要TypeScript

      我們都知道,JavaScript是弱類型的編程語(yǔ)言,很多的錯(cuò)誤只有在運(yùn)行的時(shí)候才會(huì)被發(fā)現(xiàn),而TS在代碼編譯的時(shí)候(代碼執(zhí)行前)就可以發(fā)現(xiàn)錯(cuò)誤。

      3. TypeScript的特點(diǎn)
      • 支持最新的ECMAScript語(yǔ)法
      • 在代碼編譯階段就能發(fā)現(xiàn)錯(cuò)誤
      • 在JS基礎(chǔ)上增加了類型支持
      4. TypeScript和JavaScript的區(qū)別

      TypeScript

      JavaScript

      編譯期發(fā)現(xiàn)錯(cuò)誤

      運(yùn)行時(shí)發(fā)現(xiàn)錯(cuò)誤

      強(qiáng)類型語(yǔ)言,支持靜態(tài)和動(dòng)態(tài)類型

      弱類型語(yǔ)言,沒(méi)有靜態(tài)類型選項(xiàng)

      支持模塊、泛型和接口

      不支持模塊、泛型和接口

      代碼運(yùn)行時(shí)會(huì)被編譯成JavaScript代碼,瀏覽器才能識(shí)別

      可以直接在瀏覽器使用

      二、TypeScript環(huán)境搭建1. 安裝編譯TS的工具包

      npm i g typescript

      2. 驗(yàn)證TS是否安裝成功

      tsc v

      3. TypeScript初體驗(yàn)
      1. 創(chuàng)建一個(gè)TS文件,hello.ts(注意:TS文件的后綴名為 .ts),并輸入以下的內(nèi)容

      1. 將TS文件編譯為JS文件,在終端中輸入命令:tsc hello.ts, (此時(shí),在同級(jí)目錄中會(huì)出現(xiàn)一個(gè)同名的JS文件)

      1. 執(zhí)行JS代碼:在終端中輸入命令,node hello.js,終端會(huì)輸出 hello, Echo。

      4. 簡(jiǎn)化運(yùn)行TS的步驟

      每次修改代碼后,都要重復(fù)執(zhí)行兩個(gè)命令,才能運(yùn)行TS代碼,我們可以直接使用tsnode工具包,直接在node.js中執(zhí)行TS代碼。

      安裝命令:npm i g tsnode

      使用方式:tsnode hello.ts

      5. 運(yùn)行TS文件的另一種方法

      在VSCode中安裝Code Runner擴(kuò)展插件,在需要運(yùn)行的ts文件中按鼠標(biāo)右鍵,選擇Run Code(快捷鍵:Ctrl+Alt+N)。

      6. TypeScript Playground線上環(huán)境

      對(duì)于剛?cè)腴TTypeScript的小伙伴來(lái)說(shuō),我們可以不用安裝本地的運(yùn)行環(huán)境,而是直接使用線上的 TypeScript Playground,我們就可以在瀏覽器中學(xué)習(xí)和編寫TypeScript代碼,通過(guò)配置TS Config的Target,可以設(shè)置不同的編譯目標(biāo),從而編譯生成不同的目標(biāo)代碼。

      三、TypeScript類型注解1. 類型注解作用

      TS類型注解的作用是為變量、函數(shù)、類等添加類型信息,用于在靜態(tài)類型檢查階段檢查代碼的類型正確性。

      2. 類型注解用途
      1. 提供類型提示:類型注解使得開發(fā)人員可以清晰地知道變量的類型,編輯器能夠根據(jù)類型注解給出相應(yīng)的代碼提示,提高代碼的可讀性和可維護(hù)性。
      2. 靜態(tài)類型檢查:通過(guò)給變量添加類型注解,在編譯階段可以對(duì)代碼進(jìn)行靜態(tài)類型檢查。它會(huì)檢查變量的類型是否符合預(yù)期的類型,并發(fā)現(xiàn)潛在的類型錯(cuò)誤。
      3. 函數(shù)參數(shù)類型檢查:類型注解可以幫助開發(fā)人員在編寫函數(shù)時(shí)明確參數(shù)的類型,并在調(diào)用函數(shù)時(shí)進(jìn)行參數(shù)類型檢查。這樣可以避免因參數(shù)類型不匹配引發(fā)的潛在錯(cuò)誤。
      4. 對(duì)象屬性類型約束:通過(guò)類型注解,可以約束對(duì)象的屬性類型,確保對(duì)象的屬性符合特定的類型要求。

      例如,上述代碼中的 : number 就是類型注解。 約定變量num的類型為number(數(shù)值類型)。

      3. 類型注解注意事項(xiàng)
      1. 約定了什么類型,就只能給變量賦值該類型的值,否則,就會(huì)報(bào)錯(cuò)。

      例如,我們將變量num的值123,重新賦值為字符串的“456”,此時(shí)我們就可以看到編輯器的錯(cuò)誤提示:不能將類型“string”分配給類型“number”。

      1. 類型注解只在編譯階段起作用,并不會(huì)影響運(yùn)行時(shí)的行為。 在編譯后的 JavaScript 代碼中,類型注解會(huì)被編譯器忽略。

      四、TypeScript類型1. TS中常用的基礎(chǔ)類型

      我們可以將TS中常用的基礎(chǔ)類型分為兩類:

      1. JS已有的類型
      2. TS新增的類型

      JS已有的類型,我們又可以分為兩類:

      1. 原始數(shù)據(jù)類型:number、string、boolean、null、undefined、symbol(ES6中的新類型)、bigint(ES10中的新類型)。
      2. 對(duì)象類型:object(包括數(shù)組、對(duì)象、函數(shù)等對(duì)象)。

      TS新增的類型:any、void、自定義類型(類型別名)、聯(lián)合類型、接口、元組、字面量類型、枚舉等。

      1.1. 數(shù)值(number)

      和JS一樣,TS里的所有數(shù)字都是浮點(diǎn)數(shù)。 這些浮點(diǎn)數(shù)的類型是 number。 除了支持十進(jìn)制和十六進(jìn)制字面量,TS還支持ECMAScript 2015中引入的二進(jìn)制和八進(jìn)制字面量。

      在TS中,使用 number 來(lái)定義數(shù)值類型:

      編譯結(jié)果:

      1.2. 布爾值(boolean)

      在TS中,使用 boolean 來(lái)定義布爾值類型:

      編譯結(jié)果:

      1.3. 字符串(string)

      在TS中,使用 string 來(lái)定義字符串類型:

      在TS中,字符串的表現(xiàn)形式主要有以下三種方式:

      1. 使用單引號(hào)( &39; )
      2. 使用雙引號(hào)( &34; )
      3. 使用模板字符串,它可以定義多行文本和內(nèi)嵌表達(dá)式。這種字符串是被反引號(hào)包圍( ` ),并且以 ${ expr } 這種形式嵌入表達(dá)式

      編譯結(jié)果:

      1.4. null 和 undefined

      null 和 undefined 是所有類型的子類型,默認(rèn)情況下,可以把null 和 undefined賦值給其他類型。

      注意:如果你將 tsconfig.json 文件中的 strictNullChecks 選項(xiàng)設(shè)置為 false,下面這種操作不會(huì)報(bào)錯(cuò),不過(guò)盡量不要這么做。

      編譯結(jié)果:

      注意:如果你在 tsconfig.json 文件中指定了“strictNullChecks:true”,null 和 undefined 只能賦值給 void 和它們各自的類型。

      下面這種情況會(huì)報(bào)錯(cuò):

      1.5. symbol

      symbol 是ES6新增的一種基本數(shù)據(jù)類型,Symbol()函數(shù) 會(huì)返回 symbol 類型的值,每個(gè)從 Symbol()函數(shù) 返回的 symbol 的值都是唯一的。

      上面的代碼創(chuàng)建了三個(gè)新的 symbol 類型,但是注意的是,每個(gè)從 Symbol()函數(shù) 返回的值都是唯一的。

      此時(shí),如果我們?cè)诳刂婆_(tái)打印下面的代碼,兩者并不相等。

      1.6. bigint

      bigint 是ES10新增的一種基本數(shù)據(jù)類型,在JS中,可以用 Number 表示的最大整數(shù)為 2^53 1,可以寫為 Number.MAX_SAFE_INTEGER。如果超過(guò)了這個(gè)界限,那么就可以用 BigInt 來(lái)表示,它可以表示任意大的整數(shù)。

      在一個(gè)整數(shù)字面量后面加 n 的方式定義一個(gè) bigint,或者調(diào)用函數(shù) BigInt()。

      1.7. 區(qū)別1.7.1. null 和 undefined 的區(qū)別
      1. 在JS中,null 表示“什么都沒(méi)有”,而 undefined 是一個(gè)沒(méi)有設(shè)置值的變量
      2. 用 typeof 檢測(cè) null,返回 object;typeof 一個(gè)沒(méi)有值的變量會(huì)返回 undefined
      3. null 是一個(gè)只有一個(gè)值的特殊類型,表示一個(gè)空對(duì)象的引用
      4. null 和 undefined 是其它任何類型(包括void)的子類型,可以賦值給其它類型,如數(shù)字類型,此時(shí),賦值后的類型會(huì)變成 null 或 undefined。而在TS中啟用嚴(yán)格的空校驗(yàn)(strictNullChecks)特性,就可以使得 null 和 undefined 只能被賦值給 void 或本身對(duì)應(yīng)的類型
      1.7.2. bigint 和 number 的區(qū)別
      1. number 和 bigint 都可以表示數(shù)字,但是兩者不能進(jìn)行相互轉(zhuǎn)換
      2. 僅在值大于 2^53 1時(shí),才使用 bigint,否則盡量使用 number
      3. 用 typeof 檢測(cè) bigint 對(duì)象時(shí),返回 bigint,用 typeof 檢測(cè) number,返回 number

      1.8. 對(duì)象類型1.8.1. 數(shù)組(Array)類型

      數(shù)組類型的寫法有兩種:

      1. 在類型后面加上 [],例如 number[]

      1. 使用數(shù)組泛型 <>,例如 Array

      推薦使用第一種寫法。

      注意:

      1. 如果我們定義了一個(gè)number類型的數(shù)組,此時(shí)數(shù)組的項(xiàng)中就不能出現(xiàn)其它的類型。

      1. 如果我們希望數(shù)組中既有number類型,又有string類型,此時(shí)我們可以用聯(lián)合類型來(lái)寫(關(guān)于聯(lián)合類型,后面會(huì)詳細(xì)講到)。

      上面的代碼,表示的是,定義一個(gè)arr數(shù)組,這個(gè)數(shù)組中可以出現(xiàn) number 或者 string 類型的元素。

      上面的代碼,arr1 和 arr2 都表示即可以是number類型,又可以是string[],加了小括號(hào)和不加小括號(hào),含義不同。

      1.8.2. 函數(shù)類型

      函數(shù)類型實(shí)際上指的是:函數(shù)參數(shù)和返回值的類型。

      為函數(shù)指定類型的兩種方式:

      1. 單獨(dú)指定參數(shù)、返回值的類型
      2. 同時(shí)指定參數(shù)、返回值的類型

      在JS中,有兩種常見的定義函數(shù)的方式:

      1. 函數(shù)聲明
      2. 函數(shù)表達(dá)式
      1.8.2.1. 單獨(dú)指定參數(shù)、返回值的類型

      1.8.2.2. 同時(shí)指定參數(shù)、返回值的類型

      注意:不要把ES6中的 => 和 TypeScript 中的 =>混淆了。

      在ES6中,=>叫做箭頭函數(shù)。而在 TypeScript 的類型定義中,=>用來(lái)表示函數(shù)的定義,左邊是輸入類型,需要用括號(hào)括起來(lái),右邊是輸出類型。

      1.8.2.3. 函數(shù)沒(méi)有返回值

      如果函數(shù)沒(méi)有返回值,那么,函數(shù)返回值類型為:void。

      1.8.2.4. 可選參數(shù)

      使用函數(shù)實(shí)現(xiàn)某個(gè)功能時(shí),參數(shù)可以傳也可以不傳,這種情況下,在給函數(shù)參數(shù)指定類型時(shí),就用到可選參數(shù)了。

      可選參數(shù)使用問(wèn)號(hào)( ? )標(biāo)記,表示該參數(shù)可以省略。

      上面的代碼中,我們?cè)诘诙€(gè)參數(shù) greeting 的后面加了個(gè)問(wèn)號(hào),表示在調(diào)用 greet() 函數(shù)時(shí),該參數(shù)可傳可不傳。

      注意:可選參數(shù)只能出現(xiàn)在參數(shù)列表的最后面,也就是說(shuō),可選參數(shù)后面不能再出現(xiàn)必選參數(shù)。

      錯(cuò)誤演示:下面代碼中,我們把第一個(gè)參數(shù)改為可選的,第二個(gè)參數(shù)改為必選的,然后將鼠標(biāo)移到必選參數(shù)上面,可以看到錯(cuò)誤提示:“必選參數(shù)不能位于可選參數(shù)后”。

      1.8.2.5. 參數(shù)默認(rèn)值

      在ES6中,允許給函數(shù)的參數(shù)添加默認(rèn)值,而TypeScript會(huì)將添加了默認(rèn)值的參數(shù)識(shí)別為可選參數(shù)。

      默認(rèn)參數(shù)使用等號(hào)(=)賦予默認(rèn)值。

      注意:與可選參數(shù)不同的是,帶默認(rèn)值的參數(shù)不需要放在必選參數(shù)的后面。如果帶默認(rèn)值的參數(shù)出現(xiàn)在必選參數(shù)的前面,我們?cè)谡{(diào)用函數(shù)時(shí),必須明確的傳入 undefined 值來(lái)獲得默認(rèn)值。

      1.8.2.6. 剩余參數(shù)

      使用三個(gè)點(diǎn)( ... )前綴和參數(shù)名來(lái)定義剩余參數(shù)。

      剩余參數(shù)允許我們將不確定數(shù)量的參數(shù)表示為一個(gè)數(shù)組。

      注意:剩余參數(shù)必須是函數(shù)參數(shù)列表中的最后一個(gè)參數(shù)。

      1.8.2.7. 函數(shù)重載

      函數(shù)重載允許我們?yōu)橥粋€(gè)函數(shù)提供多個(gè)函數(shù)類型定義,以便在不同的參數(shù)類型或返回值類型下進(jìn)行不同的處理。

      例如,我們現(xiàn)在需要實(shí)現(xiàn)一個(gè)函數(shù),需求是:輸入數(shù)字123,輸出反轉(zhuǎn)的數(shù)字321,輸入字符串&34;hello&34;,輸出反轉(zhuǎn)的字符串&34;olleh&34;。

      利用聯(lián)合類型,我們可以這么實(shí)現(xiàn):

      然后這樣會(huì)有一個(gè)問(wèn)題,就是輸出的類型不能準(zhǔn)確的知道,我們想輸入為數(shù)字的時(shí)候,輸出的類型應(yīng)該也為數(shù)值類型,輸入為字符串的時(shí)候,輸出類型應(yīng)該也為字符串類型。

      這時(shí),我們可以用重載定義多個(gè)reserve的函數(shù)類型:

      上述代碼中,第12行是函數(shù)定義,第39行是函數(shù)實(shí)現(xiàn)。第11行代碼,我們調(diào)用reverse函數(shù),并傳入數(shù)值123,使用typeof檢測(cè)類型為number,第12行代碼,我們調(diào)用reverse函數(shù),并傳入字符串&34;hello&34;,使用typeof檢測(cè)類型為string,這樣我們利用函數(shù)重載就實(shí)現(xiàn)了輸入為什么類型,輸出應(yīng)該也是什么類型。

      1.8.3. 對(duì)象類型

      JS中的對(duì)象是由屬性和方法構(gòu)成的,而TS中對(duì)象的類型就是在描述對(duì)象的結(jié)構(gòu)(有什么類型的屬性和方法)。

      1.8.3.1. 定義對(duì)象類型
      • 使用花括號(hào)( {} )來(lái)定義對(duì)象類型,屬性采用 屬性名: 類型 的形式;方法采用 方法名(): 返回值類型 的形式。
      • 如果方法有參數(shù),就在方法名后面的小括號(hào)中指定參數(shù)類型(比如:greet(name: string): void)。
      • 在一行代碼中指定對(duì)象的多個(gè)屬性類型時(shí),使用分號(hào)( ; )來(lái)分隔。
      • 如果一行代碼只指定一個(gè)屬性類型(通過(guò)換行來(lái)分隔多個(gè)屬性類型),可以去掉分號(hào)( ; )。
      • 方法的類型也可以使用箭頭函數(shù)形式,比如:{ sayHi: () => void }。

      上面的代碼,也可以寫成下面這種形式:

      1.8.3.2. 對(duì)象可選屬性

      對(duì)象類型中的屬性或方法可以是可選的,使用問(wèn)號(hào)( ? )標(biāo)記。

      可選屬性表示該屬性可以存在,也可以不存在。

      比如,我們?cè)谑褂胊xios({...})時(shí),如果發(fā)送GET請(qǐng)求,method屬性就可以省略。

      1.8.3.3. 對(duì)象只讀屬性

      對(duì)象的屬性也可以是只讀的,使用 readonly 關(guān)鍵字標(biāo)記。

      只讀屬性表示該屬性的值在創(chuàng)建后就不能被修改。

      2. 元組(Tuple)2.1. 元組的定義

      在 TypeScript 中,元組(Tuple)是一種特殊的數(shù)組類型,它允許 存儲(chǔ)具有固定數(shù)量和特定類型順序的元素。

      聲明一個(gè)元組的語(yǔ)法是在類型注解中使用方括號(hào) [] ,并使用逗號(hào)分隔元素的類型。

      例如,下面是一個(gè)包含兩個(gè)元素的元組:

      在上述示例中,我們聲明了一個(gè)名為 tuple 的變量,它被注解為一個(gè)元組類型 [string, number]。我們可以將一個(gè)包含兩個(gè)元素的數(shù)組賦值給 tuple,其中第一個(gè)元素是一個(gè)字符串,第二個(gè)元素是一個(gè)數(shù)字。

      2.2. 元組的特點(diǎn)
      1. 元組可以包含多個(gè)不同類型的元素,但每個(gè)元素的類型和順序是固定的。
      2. 元組的長(zhǎng)度是固定的,在創(chuàng)建元組時(shí)必須指定元素的數(shù)量。
      3. 可以通過(guò)索引訪問(wèn)元組中的元素,索引從 0 開始。
      4. 元組中的每個(gè)元素可以具有不同的類型注解。
      5. 當(dāng)訪問(wèn)元組中的元素時(shí),會(huì)根據(jù)其類型注解提供相關(guān)的類型檢查和智能提示。

      下面是一些操作元組的示例:

      注意:當(dāng)訪問(wèn)元組中的元素以及進(jìn)行元素的賦值時(shí),要確保索引和類型注解的一致性,否則可能會(huì)導(dǎo)致類型錯(cuò)誤。

      2.3. 元組類型的解構(gòu)賦值

      在 TypeScript 中,可以使用解構(gòu)賦值語(yǔ)法來(lái)從元組中提取和賦值元素。

      下面是一個(gè)簡(jiǎn)單的示例,展示了如何使用解構(gòu)賦值從元組中獲取各個(gè)元素:

      在上述示例中,我們首先聲明了一個(gè)元組 tuple,其中包含一個(gè)字符串類型的元素和一個(gè)數(shù)值類型的元素。接著,我們使用解構(gòu)賦值語(yǔ)法將元組中的元素分別賦值給變量 str 和 num。

      通過(guò)解構(gòu)賦值,我們可以直接使用對(duì)應(yīng)位置的變量來(lái)獲取元組中的元素值,而不需要通過(guò)索引訪問(wèn)。這樣可以以一種簡(jiǎn)潔、語(yǔ)義明確的方式從元組中解構(gòu)得到各個(gè)元素。

      解構(gòu)賦值還支持忽略某些元素,或者只提取部分元素。

      例如,如果只想獲取元組中的第一個(gè)元素,可以使用以下方式:

      在上述示例中,我們只聲明了一個(gè)變量 str,而忽略了后面的元素。通過(guò)解構(gòu)賦值只獲取所需元素,可以簡(jiǎn)化代碼并提高可讀性。

      另外,解構(gòu)賦值還支持使用默認(rèn)值。

      當(dāng)從元組中解構(gòu)一個(gè)不存在的元素時(shí),可以提供一個(gè)默認(rèn)值作為備選值。例如:

      在上述示例中,我們聲明了一個(gè)帶有可選的數(shù)字元素的元組 tuple,但是沒(méi)有給出對(duì)應(yīng)的數(shù)字值。在解構(gòu)賦值時(shí),如果元組中缺少對(duì)應(yīng)的元素,就會(huì)使用默認(rèn)值 undefined,這里我們將默認(rèn)值設(shè)置為 26。

      總而言之,使用解構(gòu)賦值可以輕松地從元組中提取和賦值元素,使得代碼更加簡(jiǎn)潔和可讀。它是一種方便的語(yǔ)法,特別適用于處理具有固定結(jié)構(gòu)的數(shù)據(jù)。

      注意:在解構(gòu)賦值時(shí),如果解構(gòu)數(shù)組元素的個(gè)數(shù)超過(guò)元組中元素的個(gè)數(shù),會(huì)出現(xiàn)錯(cuò)誤。

      在上述示例中,我們解構(gòu)時(shí)新增了一個(gè) sex 變量,但元組的長(zhǎng)度為 2,在索引 &34;2&34; 處沒(méi)有元素。

      2.4. 元組類型的可選元素

      在 TypeScript 中,可以使用問(wèn)號(hào) ? 來(lái)將元素定義為可選的,以表示元組中某些位置的元素是可選的。

      在上述示例中,我們定義了一個(gè)元組 tuple,該元組有兩個(gè)元素,第一個(gè)是一個(gè)字符串類型的元素,而第二個(gè)是一個(gè)可選的數(shù)值類型的元素。當(dāng)我們只提供第一個(gè)元素時(shí),第二個(gè)元素會(huì)被默認(rèn)設(shè)置為 undefined。然后,我們更新了元組的值,提供了第二個(gè)元素的值。此時(shí),元組中的兩個(gè)元素都有具體的值。

      注意,當(dāng)一個(gè)元組中包含一個(gè)可選元素時(shí),該元素可以存在或不存在,但是順序必須與元組類型定義一致。在解構(gòu)賦值時(shí),可以使用默認(rèn)值來(lái)處理可選元素的缺失情況。

      在上述示例中,我們使用解構(gòu)賦值將元組中的元素分別賦值給變量 str 和 num。由于元組只提供了一個(gè)元素,沒(méi)有提供可選的第二個(gè)元素,所以 num 的值將使用默認(rèn)值 26。

      通過(guò)使用可選元素,可以更靈活地定義元組類型,允許元組中特定位置的元素是可選的。這樣,我們可以在處理數(shù)據(jù)時(shí)更好地適應(yīng)不完整或可變的情況。

      2.5. 元組類型的剩余元素

      在 TypeScript 中,可以使用剩余元素(Rest Elements)來(lái)表示元組中剩余的元素,即將剩余的元素放入一個(gè)數(shù)組中。

      在上述示例中,我們定義了一個(gè)元組 tuple,包含一個(gè)字符串元素、一個(gè)數(shù)字元素,以及剩余元素使用剩余元素語(yǔ)法 ... 定義的布爾類型數(shù)組。在創(chuàng)建元組時(shí),我們提供了多個(gè)布爾類型的元素,它們會(huì)被放入一個(gè)數(shù)組并作為剩余元素。這樣,元組中除了前兩個(gè)元素以外的其他元素都會(huì)被放入數(shù)組中,并以數(shù)組的形式表示。

      在上述示例中,我們使用解構(gòu)賦值從元組中提取出各個(gè)元素。通過(guò)使用 ...boolArr,我們將剩余的布爾類型元素提取到名為 boolArr 的數(shù)組中。

      使用剩余元素可以處理元組中數(shù)量不確定的元素,可以更靈活地處理和操作這些元素。它提供了一種方便的方式來(lái)處理由不固定數(shù)量的元素組成的結(jié)構(gòu)數(shù)據(jù)。

      2.6. 只讀的元組類型

      在 TypeScript 中,可以使用 readonly 修飾符來(lái)創(chuàng)建只讀的元組類型,即元組中的元素不可被修改。

      在上述示例中,我們使用 readonly 修飾符將 tuple 聲明為只讀的元組類型。這意味著在運(yùn)行時(shí),我們無(wú)法修改元組中的元素的值。

      嘗試對(duì) tuple 進(jìn)行賦值或調(diào)用修改元素的方法(如 push)時(shí),TypeScript 編譯器會(huì)報(bào)錯(cuò),因?yàn)樵M被聲明為只讀,無(wú)法被修改。

      只讀的元組類型在某些場(chǎng)景下非常有用,特別是當(dāng)希望確保元組中的數(shù)據(jù)不會(huì)被意外修改時(shí)。它提供了一種強(qiáng)制保護(hù)元組數(shù)據(jù)不可變性的機(jī)制。

      3. 字面量類型

      當(dāng)我們?cè)?TypeScript 中使用字面量類型,我們可以明確指定變量只能取特定的字面量值,而不是其他可能性。這樣可以在編譯時(shí)捕獲潛在的錯(cuò)誤,并提供更好的類型推斷和類型檢查支持。

      在 TypeScript 中,可以使用多種類型的字面量進(jìn)行類型定義,包括字符串字面量類型、數(shù)字字面量類型、布爾字面量類型和符號(hào)字面量類型。

      3.1. 字符串字面量類型

      使用字符串字面量表示的類型,只能取特定的字符串值。

      3.2. 數(shù)字字面量類型

      使用數(shù)字字面量表示的類型,只能取特定的數(shù)字值。

      3.3. 布爾字面量類型

      使用布爾字面量表示的類型,只能取特定的布爾值。

      3.4. 符號(hào)字面量類型

      使用符號(hào)字面量表示的類型,只能取特定的符號(hào)值。

      字面量類型不僅可以用于變量的定義,還可以用于函數(shù)的參數(shù)、返回值、對(duì)象屬性等地方。通過(guò)使用字面量類型,我們可以在編寫代碼時(shí)明確指定特定的取值范圍,提高代碼的可讀性和可維護(hù)性。

      需要注意的是,字面量類型具有一個(gè)特殊的用途,即與聯(lián)合類型結(jié)合使用,以實(shí)現(xiàn)更精確的類型約束。例如,聯(lián)合類型 string | number 表示可以是字符串或數(shù)字類型的值,而字面量類型 &34;success&34; | &34;error&34; 表示只能是字符串 &34;success&34; 或 &34;error&34;,它們可以一起使用來(lái)實(shí)現(xiàn)更精確的類型定義。

      3.5. 函數(shù)參數(shù)中的字面量類型

      在上述示例中,函數(shù) move 的參數(shù) direction 的類型被指定為 &34;up&34; | &34;right&34; | &34;down&34; | &34;left&34;,這意味著參數(shù) direction 只能接受這四個(gè)特定的值。

      3.6. 函數(shù)返回值中的字面量類型

      在上述示例中,函數(shù) getMove 的返回值被指定為 &34;up&34; | &34;right&34; | &34;down&34; | &34;left&34;,這表示函數(shù)的返回值只能是這四個(gè)特定的值之一。

      3.7. 對(duì)象屬性中的字面量類型

      在上述示例中,Options 接口中的 mode 屬性的類型被指定為 &34;light&34; | &34;dark&34;,size 屬性的類型被指定為 &34;small&34; | &34;medium&34; | &34;large&34;,這意味著對(duì)象 config 的 mode 屬性只能是其中一個(gè)值,size 屬性也只能是其中一個(gè)值。

      3.8. let 和 const 分析3.8.1 let 聲明的字面量類型

      在上述示例中,我們使用 let 關(guān)鍵字聲明了變量 direction,并將其類型指定為 &34;Up&34; | &34;Right&34; | &34;Down&34; | &34;Left&34;,因此 direction 只能取值為 &34;Up&34; 或 &34;Right&34; 或 &34;Down&34; 或 &34;Left&34; 這四個(gè)特定值中的其中一個(gè)。

      3.8.2 const 聲明的字面量類型

      在上述示例中,我們使用 const 關(guān)鍵字聲明了常量 size,并將其類型指定為 &34;small&34; | &34;medium&34; | &34;large&34;。由于使用了 const,size 是一個(gè)只讀的常量,且初始值為 &34;medium&34;。因此,size 的值將永遠(yuǎn)是 &34;medium&34;,不能被重新賦值。

      使用 let 和 const 關(guān)鍵字來(lái)聲明變量和常量時(shí),可以配合字面量類型提供更具體和可靠的類型約束。

      注意:const 聲明的常量在聲明時(shí)必須被初始化,并且一旦初始化后,其值將不能被修改。而 let 聲明的變量可以在后續(xù)代碼中被重新賦值。

      4. 枚舉(Enum)

      枚舉(Enum)是一種用于定義一組命名常量的數(shù)據(jù)結(jié)構(gòu)。

      4.1. 基本枚舉

      在上述示例中,我們定義了一個(gè)名為 Direction 的枚舉,其中列出了 Up、Down、Left 和 Right 四個(gè)枚舉成員。默認(rèn)情況下,枚舉成員的值從 0 開始自動(dòng)遞增,因此 Direction.Up 的值為 0。我們可以使用枚舉成員來(lái)聲明變量,并進(jìn)行比較、打印等操作。

      4.2. 數(shù)字枚舉

      在默認(rèn)情況下,數(shù)字枚舉的成員從 0 開始自動(dòng)遞增。

      4.2.1. 默認(rèn)遞增的數(shù)字枚舉

      在上述示例中,我們定義了一個(gè)名為 Direction 的枚舉,其中列出了 Up、Down、Left 和 Right 四個(gè)枚舉成員。默認(rèn)情況下,枚舉成員的值從 0 開始自動(dòng)遞增,因此 Direction.Up 的值是 0,Direction.Down 的值是 1,Direction.Left 的值是 2,Direction.Right 的值是 3。

      4.2.2. 手動(dòng)賦值的數(shù)字枚舉

      在手動(dòng)賦值的數(shù)字枚舉中,可以為每個(gè)枚舉成員手動(dòng)指定一個(gè)特定的值。手動(dòng)賦值的數(shù)字枚舉可以使用任意合法的數(shù)字作為成員的值。

      在上述示例中,Direction.Up 被賦值為 2,Direction.Down 被賦值為 4,Direction.Left 被賦值為 6,Direction.Right 被賦值為 8。

      4.2.3. 計(jì)算成員的數(shù)字枚舉

      在數(shù)字枚舉中,可以使用計(jì)算表達(dá)式作為成員的值。

      在上述示例中,我們使用加法、減法、乘法和除法運(yùn)算符來(lái)計(jì)算成員的值。在編譯時(shí),這些計(jì)算表達(dá)式會(huì)被求值為結(jié)果值并成為實(shí)際的枚舉成員的值。

      4.3. 常量枚舉

      常量枚舉(const enum)是一種特殊類型的枚舉,它在編譯時(shí)被刪除,并且只保留枚舉成員的值作為常量。常量枚舉提供了一種更輕量級(jí)的方式來(lái)使用枚舉,可以用于在編譯期間替換枚舉成員的值。

      4.3.1. 常量枚舉的定義

      在定義常量枚舉時(shí),需要使用 const 關(guān)鍵字和 enum 關(guān)鍵字的組合。常量枚舉不能有計(jì)算成員。

      4.3.2. 常量枚舉的使用

      4.3.3. 常量枚舉會(huì)在編譯階段被刪除

      4.4. 字符串枚舉

      在 TypeScript 中,字符串枚舉是一種特殊類型的枚舉,其中每個(gè)成員都用字符串字面量進(jìn)行初始化。

      在上述示例中,我們定義了一個(gè)名為 Direction 的字符串枚舉。其中的成員 Up 使用字符串字面量 &34;UP&34; 進(jìn)行初始化,成員 Down 使用字符串字面量 &34;DOWN&34; 進(jìn)行初始化,成員 Left 使用字符串字面量 &34;LEFT&34; 進(jìn)行初始化,成員 Right 使用字符串字面量 &34;RIGHT&34; 進(jìn)行初始化。我們可以通過(guò)直接訪問(wèn)枚舉成員來(lái)獲得其對(duì)應(yīng)的字符串值。

      字符串枚舉的特點(diǎn):

      • 明確的字符串值:每個(gè)字符串枚舉成員都具有明確的字符串值,可更好地描述其含義和用途。
      • 代碼可讀性:由于成員的值直接使用字符串字面量,因此代碼更加清晰、易讀。
      • 保留字符串字面量:使用字符串枚舉可以在編譯后保留字符串字面量,而不是轉(zhuǎn)換為數(shù)值或其他類型。
      • 可用于反向映射:字符串枚舉可以支持從枚舉值到枚舉名的反向映射。
      4.5. 外部枚舉

      外部枚舉(ambient enum)是一種定義在外部代碼(如聲明文件)中的枚舉。外部枚舉通常用于描述已存在的枚舉類型的形狀,而不是為了創(chuàng)建一個(gè)具體的 JavaScript 對(duì)象。

      外部枚舉的定義不會(huì)在編譯時(shí)生成任何實(shí)際的 JavaScript 代碼,它只用于類型檢查。

      在上述示例中,我們使用 declare 關(guān)鍵字來(lái)定義了一個(gè)外部枚舉 HttpStatusCode。它描述了一些常見的 HTTP 狀態(tài)碼。其中的成員 OK 和 BadRequest 和 NotFound 指定了具體的數(shù)值,分別為 200,400 和 404,成員 Unauthorized 沒(méi)有顯式指定值,它會(huì)根據(jù)前一個(gè)成員的值自動(dòng)遞增,因此值為 401。

      在使用外部枚舉時(shí),我們可以像使用普通枚舉一樣,訪問(wèn)它的成員并獲得相應(yīng)的值。在上述示例中,我們將 HttpStatusCode.OK 賦值給變量 code,然后將變量 code 的值打印出來(lái),得到的結(jié)果是 200。

      注意:當(dāng)使用外部枚舉時(shí),我們必須使用 declare 來(lái)聲明它,以告訴 TypeScript 編譯器這是一個(gè)外部定義的枚舉。此外,外部枚舉的定義通常是在一個(gè)聲明文件中(以 .d.ts 結(jié)尾),以便在與現(xiàn)有 JavaScript 庫(kù)或框架進(jìn)行交互時(shí)提供類型信息。

      總結(jié)起來(lái),外部枚舉是 TypeScript 中一種在外部代碼中定義的枚舉,用于描述已存在的枚舉類型的形狀。外部枚舉的定義通常只用于類型檢查,并不會(huì)生成實(shí)際的 JavaScript 代碼。它在與現(xiàn)有 JavaScript 庫(kù)或框架進(jìn)行交互時(shí)提供類型信息。

      4.6. 異構(gòu)枚舉

      異構(gòu)枚舉(heterogeneous enum)是一種允許枚舉成員的值具有不同類型的枚舉。

      通常情況下,枚舉中的成員的值應(yīng)該是相同類型的。但是異構(gòu)枚舉允許在同一個(gè)枚舉中使用不同類型的值,包括字符串、數(shù)字和其他類型。

      在上述示例中,我們定義了一個(gè)名為 Status 的異構(gòu)枚舉。其中的成員 Active 的值是一個(gè)數(shù)字,值為 1。成員 Pending 沒(méi)有顯式指定值,它的值會(huì)根據(jù)前一個(gè)成員的值自動(dòng)遞增,因此值為 2。成員 Inactive 的值是一個(gè)字符串,值為 &34;inactive&34;。成員 OnHold 的值是一個(gè)字符串,值為 &34;on hold&34;。

      在訪問(wèn)異構(gòu)枚舉的成員時(shí),將得到其對(duì)應(yīng)的值。在上述示例中,我們分別打印了每個(gè)異構(gòu)枚舉成員的值,并相應(yīng)地獲得了不同類型的結(jié)果。

      異構(gòu)枚舉的優(yōu)勢(shì)在于允許在一組相關(guān)的枚舉中使用不同類型的值。這在某些特定情況下可能很有用,例如需要表示不同種類的狀態(tài)或類型時(shí)。

      注意:在異構(gòu)枚舉中,具有數(shù)字字面量值的成員會(huì)根據(jù)前一個(gè)成員的值自動(dòng)遞增,而具有字符串字面量值的成員不會(huì)自動(dòng)遞增。同時(shí),在異構(gòu)枚舉中,沒(méi)有初始化值的成員會(huì)根據(jù)前一個(gè)成員的值自動(dòng)遞增。

      4.7. 反向映射

      反向映射(reverse mapping)是指枚舉成員不僅可以通過(guò)名稱訪問(wèn)值,而且可以通過(guò)值訪問(wèn)名稱。 這意味著可以根據(jù)枚舉的值獲取到對(duì)應(yīng)的枚舉成員名稱。

      在上述示例中,我們定義了一個(gè)名為 Direction 的枚舉,其中的成員分別使用數(shù)字進(jìn)行初始化。我們將 Direction.Right 的值賦給變量 rightValue,然后使用 Direction[rightValue] 獲取到對(duì)應(yīng)的枚舉成員名稱,將結(jié)果賦給變量 rightName。

      在打印出變量 rightValue 和 rightName 的值后,我們得到的結(jié)果是 4 和 Right。這就是反向映射的效果,根據(jù)枚舉的值可以獲取到對(duì)應(yīng)的枚舉成員名稱。

      注意:反向映射只在數(shù)字枚舉中有效,而不適用于字符串枚舉。 字符串枚舉的成員值雖然可以是字符串字面量,但在 JavaScript 中無(wú)法實(shí)現(xiàn)反向映射。

      4.8. 運(yùn)行時(shí)的枚舉

      運(yùn)行時(shí)的枚舉(runtime enum)是指在 JavaScript 運(yùn)行時(shí)可訪問(wèn)和操作的枚舉。

      TypeScript 編譯器在編譯過(guò)程中,會(huì)將枚舉類型轉(zhuǎn)換為實(shí)際的 JavaScript 對(duì)象。這些對(duì)象在運(yùn)行時(shí)仍然保留了枚舉的結(jié)構(gòu)和值,以便能夠通過(guò)它們來(lái)進(jìn)行運(yùn)行時(shí)的枚舉操作。

      在上述示例中,我們定義了一個(gè)名為 Fruit 的枚舉,其中包含了三個(gè)成員 Apple、Orange 和 Banana。然后我們定義了一個(gè)函數(shù) getFruitName,它接受一個(gè) Fruit 類型的參數(shù),根據(jù)傳入的枚舉值返回對(duì)應(yīng)的水果名稱。

      通過(guò)運(yùn)行 getFruitName 函數(shù)并傳入不同的枚舉值,我們可以在控制臺(tái)上看到輸出的結(jié)果,它們是根據(jù)傳入的枚舉值返回的相應(yīng)水果名稱。

      注意:當(dāng)使用運(yùn)行時(shí)枚舉時(shí),由于枚舉的成員值實(shí)際上是數(shù)字(默認(rèn)從 0 開始遞增),因此進(jìn)行比較時(shí)需要使用嚴(yán)格相等運(yùn)算符 ===。

      4.9. 聯(lián)合枚舉

      聯(lián)合枚舉(union enum)是指一個(gè)枚舉類型可以包含多個(gè)不同的枚舉成員的組合。每個(gè)成員可以具有不同的值和類型。

      在上述示例中,我們定義了兩個(gè)枚舉 Shape 和 Color。Shape 枚舉表示不同的形狀,Color 枚舉表示不同的顏色。然后我們定義了一個(gè)類型別名 ShapeColor,它是 Shape 枚舉成員和 Color 枚舉成員的聯(lián)合。接著,我們定義了一個(gè)函數(shù) drawShape,它接受一個(gè) ShapeColor 類型的參數(shù) shape。根據(jù)傳入的參數(shù)值進(jìn)行不同的分支邏輯處理,并輸出相應(yīng)的消息。通過(guò)調(diào)用 drawShape 函數(shù)并傳入不同的值,我們可以根據(jù)傳入的參數(shù)值來(lái)繪制不同的形狀或填充不同的顏色。

      聯(lián)合枚舉使得我們能夠在一個(gè)類型中組合多個(gè)不同的枚舉成員,以表示更復(fù)雜的類型。這可以讓 TypeScript 的類型系統(tǒng)提供更精確的類型檢查和推斷,以確保代碼的正確性。

      注意:聯(lián)合枚舉的使用是通過(guò)定義類型別名或接口來(lái)實(shí)現(xiàn)的。 通過(guò)將不同枚舉成員組合在一起,可以創(chuàng)建復(fù)合類型,提供更靈活的數(shù)據(jù)表示。

      5. any類型

      在 TypeScript 中,any 類型表示一個(gè)動(dòng)態(tài)類型,它可以接受任何類型的值。使用 any 類型時(shí),TypeScript 編譯器將不會(huì)對(duì)值進(jìn)行類型檢查,允許你在編譯期繞過(guò)類型系統(tǒng)的限制。

      如果是一個(gè)普通類型,在賦值過(guò)程中改變類型是不被允許的。

      如果是 any 類型,則允許被賦值為任意類型。

      以下兩種情況,隱式具有 any 類型:

      • 聲明變量不提供類型也不提供默認(rèn)值。

      • 函數(shù)參數(shù)不加類型。

      注意:在開發(fā)過(guò)程中應(yīng)盡量避免過(guò)度使用 any 類型,以充分利用 TypeScript 的類型系統(tǒng)來(lái)提供更好的類型安全性和代碼可維護(hù)性。

      五、接口(interface)1. 什么是接口

      在 TypeScript 中,接口(Interface)是一種用來(lái)定義對(duì)象的結(jié)構(gòu)和行為的類型。通過(guò)接口,我們可以定義對(duì)象應(yīng)該有哪些屬性、屬性的類型以及方法。

      接口提供了一種約束和規(guī)范,使得我們可以在代碼中定義和使用特定的數(shù)據(jù)結(jié)構(gòu)。

      2. 定義接口
      • 使用關(guān)鍵字 interface 來(lái)定義接口。
      • 聲明接口后,直接使用接口名稱作為變量的類型。
      • 方法的定義和函數(shù)的定義類似,包括參數(shù)和返回值類型。
      • 接口一般首字母大寫。有的編程語(yǔ)言中建議接口的名稱加上前綴 “ I” ,“ 。”

      上面的代碼中,我們定義了一個(gè)接口 Person,接著定義了一個(gè)變量 jerry,它的類型是 Person。這樣,我們就約束了 jerry 的形狀必須和接口 Person 一致。

      注意:定義的變量比接口少了一些屬性不允許的。

      下面是一段錯(cuò)誤的代碼演示:我們定義了一個(gè)接口 Person,里面有name,age2個(gè)屬性,以及sayHi方法,接著定義了一個(gè)變量 jerry,它的類型是 Person,但是我們只給屬性name和age賦值,所以會(huì)報(bào)錯(cuò)。

      當(dāng)然,定義的變量比接口多了一些屬性也是不允許的。

      也就是說(shuō),在賦值的時(shí)候,變量的形狀必須和接口的形狀保持一致。

      3. 接口(interface)和類型別名(type)的區(qū)別
      1. 相同點(diǎn):都可以用于定義對(duì)象的結(jié)構(gòu)和類型。
      2. 不同點(diǎn):
      1. 接口更適合用于描述真實(shí)存在的對(duì)象,而類型別名更適合用于定義復(fù)雜的類型。 接口可以被其他對(duì)象實(shí)現(xiàn),而類型別名只是給類型起了一個(gè)別名。

      4. 接口繼承(extends)

      在 TypeScript 中,接口是可以相互繼承的,也就是說(shuō):一個(gè)接口可以從另一個(gè)接口中繼承屬性和方法的定義(通過(guò)繼承實(shí)現(xiàn)復(fù)用)。 接口的繼承可以通過(guò)使用關(guān)鍵字 extends 實(shí)現(xiàn)。

      接口繼承的語(yǔ)法格式如下:

      通過(guò)繼承,子接口可以獲得父接口中定義的屬性和方法,并可以在自身接口中添加新的屬性和方法。

      下面是一個(gè)簡(jiǎn)單的例子,展示了接口繼承的用法:

      在上面的例子中,使用 extends 關(guān)鍵字實(shí)現(xiàn)了接口 Circle 繼承 Shape。繼承后,Circle 就有了 Shape 中的 color 屬性,以及自身的 radius 屬性以及 getArea() 方法。

      5. 接口的可選屬性

      帶有可選屬性的接口與普通的接口定義差不多,只是在可選屬性名字定義的后面加一個(gè) ? 符號(hào)。

      上面的例子中,Person 接口中的 age 屬性是可選的,我們定義了 person1 和 person2 兩個(gè)對(duì)象,類型都是Person,其中,person1 對(duì)象中沒(méi)有 age 屬性,而 person2 對(duì)象中包含了 age 屬性。

      可選屬性的好處有2個(gè):

      1. 可以對(duì)可能存在的屬性進(jìn)行預(yù)定義
      2. 可以捕獲引用了不存在的屬性時(shí)的錯(cuò)誤

      例如,我們故意將 person2 對(duì)象中的 age 屬性名寫錯(cuò),就會(huì)得到一個(gè)錯(cuò)誤的提示。

      6. 接口的只讀屬性

      有時(shí)候我們希望某些屬性在對(duì)象創(chuàng)建后不能被修改,可以將這些屬性聲明為只讀屬性。

      通過(guò)在屬性名稱前面加上 readonly 關(guān)鍵字,就可以將屬性設(shè)置為只讀。

      例如,下面的例子中,聲明了一個(gè)名稱為 Point2D 的接口,接口中的屬性 x 和 y 都是只讀的,然后創(chuàng)建了一個(gè) point 對(duì)象,類型為 Point2D,此時(shí),我們不能再給對(duì)象中的 x 和 y 重新賦值,會(huì)報(bào)錯(cuò),因?yàn)樗鼈兌际侵蛔x屬性。

      此外 TypeScript 還提供了 ReadonlyArray 類型,它與 Array 相似,只是把所有可變方法去掉了,因此可以確保數(shù)組創(chuàng)建后再也不能被修改。

      7. 額外的屬性檢查

      接口用于定義對(duì)象的結(jié)構(gòu),當(dāng)我們使用對(duì)象字面量賦值給接口類型時(shí),TypeScript 會(huì)自動(dòng)進(jìn)行額外的屬性檢查。這意味著賦值的對(duì)象不能包含接口中未定義的額外屬性,否則會(huì)導(dǎo)致編譯錯(cuò)誤。

      在上述例子中,rect2 對(duì)象包含了額外的 color 屬性,但是接口 Rectangle 中并未定義該屬性,所以會(huì)導(dǎo)致編譯錯(cuò)誤。

      注意:如果我們確定對(duì)象會(huì)包含額外的屬性,可以使用類型斷言(Type Assertion)來(lái)繞過(guò)額外屬性檢查。

      8. 接口的任意屬性

      有時(shí)候我們希望一個(gè)接口中除了包含必選和可選屬性之外,還允許有其他的任意屬性,這時(shí)我們可以使用 索引簽名 的形式來(lái)滿足上述要求。

      上述代碼中,我們使用 [propName: string] 定義了任意屬性取 string 類型的值。

      注意:一旦定義了任意屬性,那么必選屬性和可選屬性的類型都必須是它的類型的子集:

      上述例子中,任意屬性的值允許是 string,但是可選屬性 age 的值卻是 number,number 不是 string 的子屬性,所以報(bào)錯(cuò)了。

      注意:一個(gè)接口中只能定義一個(gè)任意屬性。如果接口中有多個(gè)類型的屬性,則可以在任意屬性中使用聯(lián)合類型。

      9. 函數(shù)類型

      接口可以描述函數(shù)類型。

      為了使用接口表示函數(shù)類型,我們需要給接口定義一個(gè)調(diào)用簽名。 它就像是一個(gè)只有參數(shù)列表和返回值類型的函數(shù)定義,參數(shù)列表里的每個(gè)參數(shù)都需要名字和類型。

      在上述例子中,SearchFunc 是一個(gè)接口,它表示一個(gè)接收兩個(gè)參數(shù) source 和 subString,參數(shù)類型都為 string,并且返回值為 number 類型的函數(shù)。

      這樣定義后,我們可以像使用其它接口一樣使用這個(gè)函數(shù)類型的接口。

      下面的例子展示了如何創(chuàng)建一個(gè)函數(shù)類型的變量,并將一個(gè)同類型的函數(shù)賦值給這個(gè)變量。

      注意:對(duì)于函數(shù)類型的類型檢查來(lái)說(shuō),函數(shù)的參數(shù)名不需要與接口里定義的名字相匹配。

      例如,我們使用下面的代碼重寫上面的例子:

      函數(shù)的參數(shù)會(huì)逐個(gè)進(jìn)行檢查,要求對(duì)應(yīng)位置上的參數(shù)類型是兼容的。

      如果你不想指定類型,TypeScript 的類型系統(tǒng)會(huì)推斷出參數(shù)類型,因?yàn)楹瘮?shù)直接賦值給了 SearchFunc 類型變量。 函數(shù)的返回值類型是通過(guò)其返回值推斷出來(lái)的(此例是 false和true)。

      如果讓這個(gè)函數(shù)返回?cái)?shù)字或字符串,類型檢查器會(huì)警告我們函數(shù)的返回值類型與 SearchFunc 接口中的定義不匹配。

      10. 可索引類型

      接口可以描述具有索引簽名的對(duì)象,這樣我們就可以通過(guò)索引來(lái)訪問(wèn)對(duì)象的屬性。

      上述的例子中,我們定義了 StringArray 接口,它具有索引簽名。這個(gè)索引簽名表示了當(dāng)用 number 去索引StringArray 時(shí)會(huì)得到 string 類型的返回值。

      TypeScript 支持兩種索引簽名:字符串和數(shù)字。可以同時(shí)使用兩種類型的索引,但是數(shù)字索引的返回值必須是字符串索引返回值類型的子類型。 這是因?yàn)楫?dāng)使用 number 來(lái)索引時(shí),JavaScript 會(huì)將它轉(zhuǎn)換成 string 然后再去索引對(duì)象。 也就是說(shuō)用 100(一個(gè)number)去索引等同于使用&34;100&34;(一個(gè)string)去索引,因此兩者需要保持一致。

      11. 類類型實(shí)現(xiàn)接口

      接口可以被類實(shí)現(xiàn),稱為類類型。

      類可以通過(guò) implements 關(guān)鍵字來(lái)實(shí)現(xiàn)接口,并必須實(shí)現(xiàn)接口中定義的所有屬性和方法。

      在上述例子中,Document 類實(shí)現(xiàn)了 Printable 接口,并實(shí)現(xiàn)了接口中定義的 print 方法。

      12. 繼承接口

      和類一樣,接口也可以相互繼承。 這讓我們能夠從一個(gè)接口里復(fù)制成員到另一個(gè)接口里,可以更靈活地將接口分割到可重用的模塊里。

      一個(gè)接口可以繼承多個(gè)接口,創(chuàng)建出多個(gè)接口的合成接口。

      13. 接口繼承類

      當(dāng)接口繼承了一個(gè)類類型時(shí),它會(huì)繼承類的成員但不包括其實(shí)現(xiàn)。 就好像接口聲明了所有類中存在的成員,但并沒(méi)有提供具體實(shí)現(xiàn)一樣。 接口同樣會(huì)繼承到類的 private 和 protected 成員。 這意味著當(dāng)你創(chuàng)建了一個(gè)接口繼承了一個(gè)擁有私有或受保護(hù)的成員的類時(shí),這個(gè)接口類型只能被這個(gè)類或其子類所實(shí)現(xiàn)(implement)。

      在以上示例中,我們定義了一個(gè) Animal 類,它有一個(gè) name 屬性和一個(gè) eat 方法。然后,我們定義了一個(gè)接口 CanRun,它繼承自 Animal 類,并添加了一個(gè) run 和 eat 方法。接著,我們創(chuàng)建了一個(gè) Dog 類來(lái)實(shí)現(xiàn) CanRun 接口,并在 Dog 類中實(shí)現(xiàn)了 run 和 eat 方法。

      在最后的代碼中,我們使用 CanRun 接口來(lái)聲明一個(gè) dog 對(duì)象,并將其實(shí)例化為 Dog 類的對(duì)象。這樣,我們可以通過(guò)調(diào)用 dog 對(duì)象的 eat 和 run 方法來(lái)驗(yàn)證接口繼承類的實(shí)現(xiàn)。

      接口繼承類的主要作用在于類型標(biāo)注和約束。 通過(guò)接口繼承類,我們可以定義更具體的接口類型,使得類和接口之間的關(guān)系更加清晰。同時(shí),在使用接口類型的變量或參數(shù)時(shí),可以享受到類成員的類型檢查和智能提示的功能。這對(duì)于代碼的可讀性、可維護(hù)性和可擴(kuò)展性都有很大的幫助。

      六、類型別名

      作用:

      在 TS 中,類型別名主要用于為已有的類型創(chuàng)建別名,以便在代碼中更方便地引用和重用這些類型。

      用法:

      1. 使用 type 關(guān)鍵字可以為任何類型定義別名,包括基本類型、復(fù)雜類型、函數(shù)類型等。
      2. 創(chuàng)建類型別名后,直接使用該類型別名作為變量的類型注解即可。

      解釋:

      1. 類型別名是為已有類型提供另一個(gè)名稱,而不是創(chuàng)建新的類型。
      2. 類型別名可以用于簡(jiǎn)化復(fù)雜類型的表達(dá),提高可讀性和可維護(hù)性。
      3. 類型別名可以用于定義聯(lián)合類型或交叉類型的別名。

      注意:

      1. 盡量選擇有意義的別名,能夠準(zhǔn)確描述類型的用途,提高代碼的可讀性。
      2. 避免過(guò)度使用類型別名,過(guò)多的別名可能導(dǎo)致代碼的可維護(hù)性變差。
      3. 注意避免循環(huán)引用的情況,即在類型別名中引用自身,這會(huì)導(dǎo)致編譯錯(cuò)誤。
      4. 類型別名并不創(chuàng)建新的類型,所以它無(wú)法被繼承或?qū)崿F(xiàn)。

      七、類型推論1. 定義

      在 TypeScript 中,類型推論(Type Inference)是指編譯器在沒(méi)有明確指定類型的情況下,根據(jù)變量的值推斷出該變量的類型。 通過(guò)類型推論,TypeScript 可以在代碼中自動(dòng)推斷出變量的類型,而無(wú)需顯式地將其指定為特定類型。

      2. 基本類型推論

      當(dāng)聲明一個(gè)變量時(shí),如果沒(méi)有顯式指定類型,并且在聲明的同時(shí)進(jìn)行了賦值操作,TypeScript 將根據(jù)賦值的值推斷出變量的類型。

      3. 上下文類型推論

      當(dāng)變量的類型與其所處的上下文相關(guān)時(shí),TypeScript 可以根據(jù)上下文進(jìn)行類型推斷。

      在上述示例中,函數(shù) add 接收兩個(gè)參數(shù),并返回它們的和。當(dāng)我們調(diào)用 add(5, 10) 時(shí),TypeScript 根據(jù)函數(shù)返回值的類型推斷出 result 變量的類型為 number。

      4. 最佳通用類型推論

      當(dāng)需要推斷出數(shù)組或?qū)ο箢愋蜁r(shí),TypeScript 會(huì)根據(jù)元素或?qū)傩缘念愋屯茢喑鲆粋€(gè)“最佳通用類型”。

      在上述示例中,數(shù)組 numbers 中的所有元素都是數(shù)字,因此 TypeScript 推斷出 numbers 的類型為 number[]。而數(shù)組 mixed 中的元素類型不同(數(shù)字、字符串和布爾值),所以 TypeScript 推斷出 mixed 的類型為 (number | string | boolean)[],表示該數(shù)組可以存儲(chǔ)數(shù)字、字符串或布爾值類型的元素。

      5. 聲明變量但沒(méi)有賦值的情況

      如果聲明變量的時(shí)候沒(méi)有賦值,不管之后有沒(méi)有賦值,都會(huì)被推斷成 any 類型而完全不被類型檢查。

      在上述示例中,變量 str 的類型推斷為 any 類型,因?yàn)樗鼪](méi)有明確的初始值。此時(shí)我們就可以把任意類型的值賦值給 str。

      需要注意的是,雖然 TypeScript 可以根據(jù)賦值來(lái)推斷類型,但如果變量的初始值為 null 或 undefined,類型推論仍然會(huì)將其推斷為 any 類型。

      為了避免使用 any 類型,我們可以顯式指定變量的類型或?yàn)樽兞刻峁┮粋€(gè)初始值來(lái)觸發(fā)類型推論。

      八、類型斷言1. 定義

      類型斷言(Type Assertion)是 TypeScript 中的一種表達(dá)式,它可以用來(lái)告訴編譯器一個(gè)值的確切類型。通過(guò)類型斷言,我們可以在一些情況下主動(dòng)指定變量的類型,以滿足特定的需求。

      2. 語(yǔ)法

      類型斷言有2種語(yǔ)法形式:

      1. 尖括號(hào)語(yǔ)法: 使用尖括號(hào) <> 將值包裹,并在尖括號(hào)內(nèi)指定目標(biāo)類型。 <類型>值

      在上面的示例中,我們將變量 value 的類型斷言為 string 類型,然后使用 .length 屬性獲取字符串的長(zhǎng)度。

      1. as 語(yǔ)法: 使用 as 關(guān)鍵字,在值后面跟上目標(biāo)類型。值 as 類型

      在上面的示例中,我們使用 as 關(guān)鍵字將變量 value 的類型斷言為 string 類型,并用 length 屬性獲取字符串的長(zhǎng)度。

      以上兩種語(yǔ)法雖說(shuō)沒(méi)有太大的區(qū)別,但是我們更推薦使用 as 語(yǔ)法。因?yàn)榧饫ㄌ?hào)格式會(huì)與 react 中 JSX 產(chǎn)生語(yǔ)法沖突。

      3. 任何類型可以斷言為 any 類型

      由于 any 類型可以接收任何值,因此任何類型都可以斷言為 any 類型。這樣的斷言并不提供更多的類型檢查,因此在使用類型斷言時(shí)需要謹(jǐn)慎。

      上面的例子中,數(shù)字類型的變量 foo 上是沒(méi)有 length 屬性的,故 TypeScript 給出了相應(yīng)的錯(cuò)誤提示。

      這種錯(cuò)誤提示顯然是非常有用的。

      但有的時(shí)候,我們非常確定這段代碼不會(huì)出錯(cuò),比如下面這個(gè)例子:

      上面的示例中,我們需要將 window 上添加一個(gè)屬性 bar,但 TypeScript 編譯時(shí)會(huì)報(bào)錯(cuò),提示我們 window 上不存在 屬性 bar。

      此時(shí)我們可以使用 as any 臨時(shí)將 window 斷言為 any 類型:

      4. any 類型可以斷言為任何類型

      與上述情況相反,由于 any 類型可以接收任何值,它可以被斷言為任何類型。這樣的斷言會(huì)跳過(guò)類型檢查,因此潛在的類型錯(cuò)誤可能發(fā)生。

      5. 聯(lián)合類型的類型斷言

      當(dāng)變量具有聯(lián)合類型時(shí),我們可以通過(guò)類型斷言將其斷言為其中的一個(gè)類型,但是必須確保斷言的類型是變量實(shí)際上可以具備的類型。

      6. 類型斷言的限制6.1. 類型斷言不會(huì)改變變量的實(shí)際類型

      類型斷言只是告訴編譯器將一個(gè)值視為特定類型,并不會(huì)改變?cè)撝档膶?shí)際類型。在運(yùn)行時(shí),類型斷言不會(huì)影響變量的值或行為,它只是在編譯時(shí)起作用。

      6.2. 類型斷言不能用于基本類型之間的轉(zhuǎn)換

      TypeScript 的類型斷言不能用于將基本類型(如 number、string、boolean)相互轉(zhuǎn)換。因?yàn)榛绢愋途哂忻鞔_的類型判斷和行為,不能將一個(gè)基本類型斷言為另一個(gè)基本類型。

      6.3. 類型斷言不能覆蓋類型檢查

      類型斷言可以繞過(guò)編譯器的類型檢查,但并不意味著我們可以隨意斷言任何類型。如果發(fā)生類型斷言與變量的實(shí)際類型不匹配的情況,可能會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。

      6.4. 類型斷言不能將 null 或 undefined 斷言為其他類型

      因?yàn)?null 和 undefined 可以被賦值給任何類型,將它們斷言為其他類型是沒(méi)有意義的。

      6.5. 聯(lián)合類型的類型斷言存在類型互相排斥的限制

      如果將一個(gè)變量斷言為聯(lián)合類型中某個(gè)類型,那么它必須是該聯(lián)合類型中的實(shí)際類型之一。

      7. 雙重?cái)嘌?p datatrack="737">雙重?cái)嘌裕―ouble Assertion),也被稱為雙重類型斷言或連續(xù)類型斷言,是一種在 TypeScript 中連續(xù)使用類型斷言的技術(shù)。它是將一個(gè)值斷言為多個(gè)類型的一種嘗試,盡管這種用法并不被 TypeScript 官方鼓勵(lì)使用,因?yàn)樗赡墚a(chǎn)生不可預(yù)測(cè)的結(jié)果。

      雙重?cái)嘌缘男问绞鞘褂眠B續(xù)的類型斷言操作符 as 或尖括號(hào) <> 來(lái)表示:

      在上述示例中,我們連續(xù)使用了兩次類型斷言,將值 value 先斷言為 any 類型,然后再將其斷言為 string 類型,并使用 length 屬性獲取字符串的長(zhǎng)度。但是需要注意的是,盡管代碼通過(guò)了編譯,但是這種雙重?cái)嘌缘姆椒ú⒉话踩驗(yàn)樗梢詫?dǎo)致類型錯(cuò)誤和運(yùn)行時(shí)錯(cuò)誤。

      使用雙重?cái)嘌钥赡軙?huì)隱藏類型錯(cuò)誤,因?yàn)轭愋蛿嘌允蔷幾g時(shí)的操作,而不是運(yùn)行時(shí)。在運(yùn)行時(shí),雙重?cái)嘌钥赡軙?huì)導(dǎo)致意外的類型轉(zhuǎn)換錯(cuò)誤,并且編譯器無(wú)法為此提供任何保護(hù)。

      所以,在實(shí)際開發(fā)中,應(yīng)盡量避免使用雙重?cái)嘌浴H绻枰褂枚鄠€(gè)類型,而無(wú)法使用更安全的方法來(lái)表示,可以考慮重構(gòu)代碼,使用更合適的類型來(lái)處理多種情況,或者使用類型守衛(wèi)和類型判斷等 TypeScript 提供的更安全的技術(shù)來(lái)處理復(fù)雜的類型轉(zhuǎn)換或條件判斷。

      8. 類型斷言VS類型轉(zhuǎn)換

      在 TypeScript 中,類型斷言(Type Assertion) 是一種在編譯時(shí)告訴編譯器一個(gè)值的確切類型的方式,它只是一種類型的聲明,不會(huì)對(duì)變量進(jìn)行真正的類型轉(zhuǎn)換。

      與類型斷言相對(duì)的是類型轉(zhuǎn)換(Type Casting) ,它是將一個(gè)值從一種類型轉(zhuǎn)換為另一種類型的實(shí)際操作,而不僅僅是告訴編譯器某個(gè)值的類型。類型轉(zhuǎn)換通常需要在運(yùn)行時(shí)進(jìn)行,并涉及對(duì)值的實(shí)際修改。

      在上述示例中,(value as string) 是一種類型斷言,告訴編譯器將變量 value 視為字符串類型。而 parseInt 是一種類型轉(zhuǎn)換,將字符串類型的 numberValue 轉(zhuǎn)換為整數(shù)類型。

      需要注意的是,類型斷言只會(huì)在編譯時(shí)起作用,不會(huì)對(duì)變量進(jìn)行實(shí)際的類型轉(zhuǎn)換。而類型轉(zhuǎn)換涉及到對(duì)變量值的修改,通常發(fā)生在運(yùn)行時(shí)。

      盡管類型斷言和類型轉(zhuǎn)換在某種程度上可以實(shí)現(xiàn)相似的效果,但它們的機(jī)制和目的不同。類型斷言是為了輔助編譯器進(jìn)行類型推斷和類型檢查的工具,而類型轉(zhuǎn)換是為了實(shí)際修改變量的類型以滿足特定需求。因此,在使用類型轉(zhuǎn)換時(shí),需要注意潛在的類型錯(cuò)誤和運(yùn)行時(shí)錯(cuò)誤,并謹(jǐn)慎處理類型轉(zhuǎn)換的結(jié)果。

      9. 類型斷言VS類型聲明

      在 TypeScript 中,類型斷言(Type Assertion) 是一種在編譯時(shí)告訴編譯器一個(gè)值的確切類型的方式,它是開發(fā)者主動(dòng)指定一個(gè)變量的類型,并告訴編譯器遵循這個(gè)類型進(jìn)行類型檢查。通過(guò)類型斷言,我們可以在某些情況下繞過(guò)編譯器的類型檢查,但這需要開發(fā)者對(duì)類型的準(zhǔn)確性負(fù)責(zé),并且存在潛在的類型錯(cuò)誤的風(fēng)險(xiǎn)。

      在上述示例中,(value as string) 是一種類型斷言,將變量 value 的類型斷言為字符串類型,從而可以安全地訪問(wèn)字符串的 length 屬性。

      類型聲明(Type Declaration) 是一種為變量、參數(shù)、返回值等明確指定類型的語(yǔ)法,它是用來(lái)定義變量的類型,并告訴編譯器如何對(duì)變量進(jìn)行類型推斷和類型檢查。類型聲明通常出現(xiàn)在變量聲明、函數(shù)聲明、函數(shù)參數(shù)、函數(shù)返回值等地方,例如:

      在上述示例中,value: string 是對(duì)變量 value 進(jìn)行類型聲明,指定其類型為字符串。而 name: string 是對(duì)函數(shù)參數(shù) name 進(jìn)行類型聲明,指定其類型為字符串。這樣可以確保編譯器在類型檢查時(shí)能夠發(fā)現(xiàn)潛在的類型錯(cuò)誤。

      類型聲明是 TypeScript 中一種重要的類型系統(tǒng)的特性,它提供了對(duì)變量類型的明確說(shuō)明,使開發(fā)者能夠編寫更加安全和可維護(hù)的代碼。與類型斷言相比,類型聲明更加強(qiáng)制,能夠更好地幫助開發(fā)者在編譯時(shí)發(fā)現(xiàn)類型錯(cuò)誤,并提供更好的類型推斷和類型檢查支持。

      10. 類型斷言和泛型

      在 TypeScript 中,類型斷言(Type Assertion) 是一種在編譯時(shí)告訴編譯器一個(gè)值的確切類型的方式,它是開發(fā)者主動(dòng)指定一個(gè)變量的類型,并告訴編譯器遵循這個(gè)類型進(jìn)行類型檢查。通過(guò)類型斷言,我們可以在某些情況下繞過(guò)編譯器的類型檢查,但這需要開發(fā)者對(duì)類型的準(zhǔn)確性負(fù)責(zé),并且存在潛在的類型錯(cuò)誤的風(fēng)險(xiǎn)。

      在上述示例中,(value as string) 是一種類型斷言,將變量 value 的類型斷言為字符串類型,以便可以安全地訪問(wèn)字符串的 length 屬性。

      泛型是一種在定義函數(shù)、類或接口時(shí)使用類型參數(shù)來(lái)表示靈活的類型的方式。通過(guò)泛型,我們可以在定義時(shí)不指定具體類型,而是在使用時(shí)根據(jù)上下文傳入具體的類型。它可以增加代碼的重用性和靈活性。例如:

      在上述示例中,toArray 是一個(gè)泛型函數(shù),使用類型參數(shù) T 來(lái)表示數(shù)組中的元素類型。通過(guò)傳入具體的類型 &34;Hello&34;,我們可以創(chuàng)建一個(gè)字符串類型的數(shù)組。

      類型斷言和泛型實(shí)際上可以一起使用。當(dāng)我們?cè)谔幚矸盒皖愋蜁r(shí),有時(shí)可能需要對(duì)類型進(jìn)行斷言以滿足特定的需求。例如:

      在上述示例中,通過(guò)連續(xù)使用類型斷言,我們將泛型類型 T 先斷言為 unknown 類型,然后再斷言為字符串類型,將參數(shù) value 轉(zhuǎn)換為字符串類型并返回。

      需要注意的是,在使用類型斷言和泛型時(shí),我們要確保類型的安全性和正確性,并避免潛在的類型錯(cuò)誤。類型斷言可以幫助我們處理一些特殊情況,但要謹(jǐn)慎使用,并確保斷言的類型與變量的實(shí)際類型相符。泛型則是一種更加靈活和通用的方式來(lái)處理不特定類型的代碼邏輯。

      九、類(class)1. 類的定義

      在 TypeScript 中,可以使用 class 關(guān)鍵字來(lái)定義類。類的定義通常包括成員變量、構(gòu)造函數(shù)、方法等。

      2. 類的基本使用

      類的基本使用主要有以下幾個(gè)步驟:

      1. 定義類及成員變量: 使用 class 關(guān)鍵字定義一個(gè)類,并在類中聲明成員變量。
      2. 構(gòu)造函數(shù): 使用 constructor 方法定義構(gòu)造函數(shù),用于在創(chuàng)建類的實(shí)例時(shí)初始化對(duì)象的屬性。
      3. 方法: 在類中定義方法,可通過(guò)類的實(shí)例調(diào)用。
      4. 創(chuàng)建類的實(shí)例: 使用 new 關(guān)鍵字創(chuàng)建類的實(shí)例,并傳遞構(gòu)造函數(shù)所需的參數(shù)。
      5. 訪問(wèn)成員變量和調(diào)用方法: 通過(guò)實(shí)例對(duì)象訪問(wèn)成員變量和調(diào)用方法。

      在上述示例中:我們使用 class 關(guān)鍵字定義一個(gè)名為 Person 的類,并在 Person 類中聲明了兩個(gè)成員變量:name 和 age。接著,我們使用 constructor 方法定義一個(gè)構(gòu)造函數(shù),用于在創(chuàng)建類的實(shí)例時(shí)初始化對(duì)象的屬性,構(gòu)造函數(shù)參數(shù) name 和 age 分別用于接收傳入的 name 和 age 值,并將其賦給對(duì)應(yīng)的成員變量。然后定義了一個(gè)名為 sayHello 的方法,用于打印一個(gè)問(wèn)候語(yǔ),并使用成員變量 name 和 age。接著,我們使用 new 關(guān)鍵字創(chuàng)建一個(gè) Person 實(shí)例 p,然后打印出 name 和 age 的值以及調(diào)用 sayHello 方法。

      3. 類的構(gòu)造函數(shù)

      在 TypeScript 類中,構(gòu)造函數(shù)是一種特殊的方法,用于在創(chuàng)建類的實(shí)例時(shí)進(jìn)行初始化操作。構(gòu)造函數(shù)使用 constructor 關(guān)鍵字來(lái)定義,可以接收參數(shù),并在創(chuàng)建對(duì)象時(shí)調(diào)用。

      3.1. 構(gòu)造函數(shù)的基本語(yǔ)法

      在上面的代碼中,ClassName 是類的名稱,parameter1、parameter2 等表示構(gòu)造函數(shù)的參數(shù)名,Type1、Type2 等表示參數(shù)的類型。

      3.2. 使用構(gòu)造函數(shù)初始化成員變量

      構(gòu)造函數(shù)可以用來(lái)初始化類中的成員變量,通過(guò)接收構(gòu)造函數(shù)的參數(shù),并將其賦給對(duì)應(yīng)的成員變量。成員變量的聲明通常放在類的頂部,而初始化則在構(gòu)造函數(shù)中進(jìn)行。

      在上述示例中,構(gòu)造函數(shù)接收 name 和 age 作為參數(shù),并將參數(shù)的值分別賦給類中的 name 和 age 成員變量。

      3.3. 創(chuàng)建類的實(shí)例并調(diào)用構(gòu)造函數(shù)

      使用 new 關(guān)鍵字創(chuàng)建類的實(shí)例時(shí),構(gòu)造函數(shù)會(huì)被自動(dòng)調(diào)用,讓我們可以在創(chuàng)建實(shí)例的同時(shí)進(jìn)行初始化操作。

      在上述代碼中,我們創(chuàng)建了一個(gè) Person 類的實(shí)例 person,并傳遞了 &39;Echo&39; 和 26 作為構(gòu)造函數(shù)的參數(shù)。構(gòu)造函數(shù)會(huì)將這些參數(shù)的值分別賦給 person 實(shí)例的 name 和age 成員變量。

      3.4. 構(gòu)造函數(shù)的可選參數(shù)和默認(rèn)值

      構(gòu)造函數(shù)的參數(shù)可以設(shè)置為可選的,并且可以為參數(shù)提供默認(rèn)值。

      可選參數(shù)使用問(wèn)號(hào)( ? )修飾符進(jìn)行標(biāo)記,而默認(rèn)值則使用等號(hào)(=)進(jìn)行賦值。

      在上述示例中,name 參數(shù)具有一個(gè)默認(rèn)值 &39;Echo&39;,而 age 參數(shù)則是可選的。如果在創(chuàng)建實(shí)例時(shí)不傳 name 和 age 參數(shù),那么 name 會(huì)輸出默認(rèn)值 &39;Echo&39;,而 age 會(huì)被設(shè)置為 undefined,如果在創(chuàng)建實(shí)例時(shí)只傳遞了 name 參數(shù),而沒(méi)有傳遞 age 參數(shù),那么 age 也會(huì)被設(shè)置為 undefined。

      3.5 .調(diào)用其他構(gòu)造函數(shù)(構(gòu)造函數(shù)重載)

      在一個(gè)類中,可以定義多個(gè)構(gòu)造函數(shù),并通過(guò)不同的參數(shù)配置來(lái)進(jìn)行重載。重載的構(gòu)造函數(shù)之間可以相互調(diào)用,使用 this 關(guān)鍵字來(lái)引用當(dāng)前類的實(shí)例。

      構(gòu)造函數(shù)重載需要定義多個(gè)具有不同參數(shù)類型和數(shù)量的構(gòu)造函數(shù)簽名。構(gòu)造函數(shù)簽名是指構(gòu)造函數(shù)名稱和參數(shù)列表,通過(guò)這些不同的簽名來(lái)區(qū)分不同的構(gòu)造函數(shù)。

      在上面的示例中,我們定義了三個(gè)構(gòu)造函數(shù)簽名,每個(gè)簽名有不同的參數(shù)類型和數(shù)量,以提供不同的構(gòu)造函數(shù)選項(xiàng)。

      在上述示例中,我們定義了兩個(gè)構(gòu)造函數(shù)簽名,第一個(gè)構(gòu)造函數(shù)接收一個(gè) name 參數(shù),第二個(gè)構(gòu)造函數(shù)接收一個(gè) name 和一個(gè) age 參數(shù)。在構(gòu)造函數(shù)的實(shí)現(xiàn)中,根據(jù)傳遞的參數(shù)情況,決定是否給 age 成員變量賦值。接著,我們創(chuàng)建了兩個(gè)實(shí)例 person1 和 person2,第一次實(shí)例化傳遞了一個(gè) name 參數(shù),調(diào)用了第一個(gè)構(gòu)造函數(shù)。第二次實(shí)例化傳遞了一個(gè) name 參數(shù)和一個(gè) age 參數(shù),調(diào)用了第二個(gè)構(gòu)造函數(shù)。

      注意:

      • 成員初始化(比如 name: string)后,才可以通過(guò) this.name 來(lái)訪問(wèn)實(shí)例成員。
      • 需要為構(gòu)造函數(shù)指定類型注解,否則會(huì)被隱式推斷為 any 類型,構(gòu)造函數(shù)不需要返回值類型。
      4. 類的實(shí)例方法

      在 TypeScript 類中,實(shí)例方法是定義在類中的成員方法,用于操作和訪問(wèn)類的實(shí)例屬性,并執(zhí)行特定的操作。實(shí)例方法可以通過(guò)類的實(shí)例來(lái)調(diào)用,用于對(duì)特定實(shí)例進(jìn)行特定操作。

      4.1. 定義實(shí)例方法

      實(shí)例方法是通過(guò)在類中定義普通函數(shù)來(lái)創(chuàng)建的。語(yǔ)法格式如下:

      在上面的示例中,methodName 是實(shí)例方法的名稱,parameter1 和 parameter2 是方法的參數(shù),Type1 和 Type2 是參數(shù)的類型,ReturnType 是方法的返回類型。

      4.2. 訪問(wèn)實(shí)例屬性

      實(shí)例方法可以通過(guò)使用 this 關(guān)鍵字直接訪問(wèn)類的實(shí)例屬性。

      在上述示例中,sayHello 是一個(gè)實(shí)例方法,它訪問(wèn)了 Person 類的 name 和 age 屬性,并在控制臺(tái)打印出相應(yīng)的消息。

      4.3. 調(diào)用實(shí)例方法

      實(shí)例方法必須通過(guò)類的實(shí)例來(lái)調(diào)用。

      在上述示例中,我們首先創(chuàng)建了一個(gè) Person 類的實(shí)例 person,然后使用 person 實(shí)例來(lái)調(diào)用 sayHello 方法。

      5. 類的繼承

      類的繼承有2種方式:

      1. extends(繼承父類)
      2. implements(實(shí)現(xiàn)接口)

      說(shuō)明:JS 中只有 extends,而 implements 是 TS 提供的。

      5.1. extends(繼承父類)

      當(dāng)一個(gè)類繼承另一個(gè)類時(shí),它會(huì)繼承父類的屬性和方法,并可以通過(guò)重載或添加新的屬性和方法來(lái)擴(kuò)展父類。繼承使用 extends 關(guān)鍵字來(lái)建立類之間的關(guān)系。

      5.1.1. 定義父類和子類

      父類是被繼承的類,子類是繼承父類的類。

      在上面的示例中,ParentClass 是父類,ChildClass 是子類,ChildClass 繼承了 ParentClass 的屬性和方法。

      5.1.2. 繼承父類的屬性和方法

      使用 extends 關(guān)鍵字來(lái)建立子類對(duì)父類的繼承關(guān)系。子類會(huì)繼承父類的公共成員(屬性和方法)。子類可以直接訪問(wèn)和使用繼承來(lái)的屬性和方法。

      在上述示例中,Animal 是父類,其中包含了 name 屬性和 move 方法。Dog 是子類,使用 extends Animal 建立了繼承關(guān)系。Dog 繼承了 Animal 的屬性和方法,并且定義了自己的 bark 方法。

      5.1.3. 調(diào)用繼承的屬性和方法

      子類可以直接調(diào)用繼承來(lái)的父類屬性和方法,也可以訪問(wèn)自己定義的屬性和方法。

      在上述示例中,我們首先創(chuàng)建了一個(gè) Dog 類的實(shí)例 dog。我們可以通過(guò) dog 實(shí)例調(diào)用繼承自父類的 move 方法,也可以調(diào)用子類自己定義的 bark 方法。

      5.2. implements(實(shí)現(xiàn)接口)

      接口的實(shí)現(xiàn)是以類為基礎(chǔ)的,類可以通過(guò) implements 關(guān)鍵字實(shí)現(xiàn)一個(gè)或多個(gè)接口。通過(guò)實(shí)現(xiàn)接口,類必須提供接口中定義的所有屬性和方法的具體實(shí)現(xiàn)。

      5.2.1. 定義接口

      接口是一種抽象的類型,定義了一組屬性和方法的規(guī)范。接口在定義時(shí)不包含具體的實(shí)現(xiàn),而是描述了類應(yīng)具備的特定行為和功能。

      在上面的示例中,InterfaceName 是一個(gè)接口,用于定義屬性和方法的規(guī)范。

      5.2.2. 使用 implements 實(shí)現(xiàn)接口

      使用 implements 關(guān)鍵字來(lái)實(shí)現(xiàn)接口,使得類能夠滿足接口定義的規(guī)范。通過(guò)實(shí)現(xiàn)接口,類必須提供接口中定義的所有屬性和方法的具體實(shí)現(xiàn)。

      在上述示例中,ClassName 是一個(gè)類,通過(guò) implements InterfaceName 實(shí)現(xiàn)了接口 InterfaceName,從而滿足了接口定義的規(guī)范。

      5.2.3. 實(shí)現(xiàn)接口的屬性和方法

      實(shí)現(xiàn)接口的類必須包含接口中定義的所有屬性和方法,并提供它們的具體實(shí)現(xiàn)。

      在上面的示例中,Shape 是一個(gè)接口,定義了屬性 color 和方法 getArea()。Circle 類通過(guò) implements Shape 實(shí)現(xiàn)了接口 Shape,并提供了接口中定義的屬性和方法的具體實(shí)現(xiàn)。

      6. 類的修飾符

      在 TypeScript 中,類的修飾符用于控制類的成員(屬性和方法)的可見性和訪問(wèn)權(quán)限。

      類的修飾符包括:

      1. public(公有的),可以在任何地方被訪問(wèn)到,默認(rèn)所有的屬性和方法都是 public 的。
      2. privete(私有的),不能在聲明它的類的外部訪問(wèn)。
      3. protected(受保護(hù)的),和 private 類似,區(qū)別是它在子類中也是允許被訪問(wèn)的。
      6.1. public

      public 關(guān)鍵字是默認(rèn)的訪問(wèn)修飾符,如果不指定修飾符,默認(rèn)為 public。公共成員在類的內(nèi)部和外部都是可見的,并且可以隨時(shí)訪問(wèn)。

      在上述示例中,name、age 和 sayHello() 都是公共成員,可以在類的內(nèi)部和外部進(jìn)行訪問(wèn)。

      6.2. private

      private 關(guān)鍵字修飾符限制成員的訪問(wèn)范圍僅在類的內(nèi)部。私有成員在類的外部不可見,只能在類的內(nèi)部進(jìn)行訪問(wèn)。

      在上述示例中,成員 name 是私有成員,只能在類的內(nèi)部進(jìn)行訪問(wèn),外部訪問(wèn)會(huì)報(bào)錯(cuò)。

      注意:1. 使用 private 修飾的屬性或方法,在子類中也是不允許訪問(wèn)的。

      注意:2. 當(dāng)構(gòu)造函數(shù)修飾為 private 時(shí),該類不允許被繼承或者實(shí)例化。

      6.3. protected

      protected 關(guān)鍵字修飾符限制成員的訪問(wèn)范圍在類的內(nèi)部及其派生類中。受保護(hù)成員在類的外部不可見,但可以在類的內(nèi)部和派生類中進(jìn)行訪問(wèn)。

      注意:當(dāng)構(gòu)造函數(shù)修飾為 protected 時(shí),該類只允許被繼承。

      6.4. readonly

      readonly 是一個(gè)只讀屬性關(guān)鍵字,只允許出現(xiàn)在屬性聲明或索引簽名或構(gòu)造函數(shù)中。

      注意:如果 readonly 和其他訪問(wèn)修飾符同時(shí)存在的話,需要寫在其后面。

      readonly 只讀屬性特點(diǎn):

      • 只讀屬性必須在聲明時(shí)或索引簽名或構(gòu)造函數(shù)內(nèi)進(jìn)行初始化賦值。
      • 只讀屬性不能被重新賦值或修改,否則會(huì)報(bào)錯(cuò)。
      • 只能修飾屬性,不能修飾方法。

      只讀屬性和常量的區(qū)別:

      • 只讀屬性是 TypeScript 提供的一種語(yǔ)法,用于將類的屬性標(biāo)記為只讀,并且只有在類的內(nèi)部可以修改其值。
      • 常量通常是通過(guò) const 關(guān)鍵字聲明的,在任何地方都無(wú)法修改其值,包括類的內(nèi)部。
      6.5. 參數(shù)屬性

      參數(shù)屬性是一種簡(jiǎn)化代碼的語(yǔ)法糖,用于在構(gòu)造函數(shù)中同時(shí)聲明和初始化類的成員屬性。使用參數(shù)屬性可以在一個(gè)地方完成屬性的聲明和賦值,減少了重復(fù)的代碼。

      在上述示例中,定義了一個(gè)名為 Person 的類,類里面定義了一個(gè) constructor 構(gòu)造方法,其中參數(shù) name 是公共屬性,可以在類的內(nèi)部和外部訪問(wèn);參數(shù) age 是私有屬性,只能在類 Person 中訪問(wèn);參數(shù) sex 是受保護(hù)屬性,只能在類 Person 及其子類中訪問(wèn);參數(shù) height 是只讀屬性,類的外部無(wú)法修改其值。

      7. 抽象類

      使用關(guān)鍵字 abstract 用于定義抽象類和其中的抽象方法。

      抽象類是一種不能直接實(shí)例化的類,它主要用作其他類的基類。抽象類可以包含抽象方法和具體方法的定義,供子類繼承和實(shí)現(xiàn)。

      7.1. 語(yǔ)法

      在上述示例中,AbstractClass 是一個(gè)抽象類,它包含了一個(gè)抽象方法 method() 和一個(gè)具體方法 concreteMethod()。

      7.2. 抽象方法

      抽象方法是在抽象類中聲明但沒(méi)有具體實(shí)現(xiàn)的方法。它只包含方法的簽名,沒(méi)有方法體,子類必須實(shí)現(xiàn)抽象方法。

      在上述示例中,抽象類 Animal 中的 sayHi() 是一個(gè)抽象方法,子類 Cat 繼承了 父類 Animal 并實(shí)現(xiàn)了抽象方法。

      7.3. 抽象類不能被實(shí)例化,只能被繼承

      抽象類不能被實(shí)例化,只能被繼承。

      7.4. 特點(diǎn)
      • 抽象類不能被實(shí)例化,只能被繼承。
      • 抽象類可以包含抽象方法和具體方法的定義。
      • 子類必須實(shí)現(xiàn)抽象類中的所有抽象方法,否則子類也必須聲明為抽象類。
      • 如果一個(gè)類繼承了一個(gè)抽象類,那么它必須實(shí)現(xiàn)抽象類中的抽象方法,除非它自身也聲明為抽象類。
      • 抽象類可以作為其他類的基類,用于提供共享的屬性和方法定義。
      十、類型兼容性

      類型兼容性是指在 TS 中,如何判斷一個(gè)類型是否能夠賦值給另一個(gè)類型。

      1. 基本類型的兼容性1.1. 相同的基本類型可以互相賦值

      當(dāng)你聲明一個(gè)變量并為其賦予一個(gè)特定類型的值時(shí),TypeScript 會(huì)根據(jù)類型注解進(jìn)行類型檢查和推斷。如果變量的類型與給定的值的類型完全匹配,那么它們可以互相賦值。

      在上述示例中,變量 a 被聲明為 number 類型,并且被賦值為 10。 然后將變量 a 賦值給變量 b,因?yàn)?a 和 b 的類型相同,都是 number,所以賦值是允許的。

      1.2. 數(shù)字字面量類型可以賦值給數(shù)值類型

      當(dāng)你聲明一個(gè)變量并為其指定為數(shù)字字面量類型時(shí),TypeScript 會(huì)將該變量視為一個(gè)特定的數(shù)字值,而不僅僅是一般的數(shù)值類型。

      在這個(gè)示例中,變量 a 被聲明為數(shù)字字面量類型 10,它只能具有值 10,而不能是其它的值。然后將變量 a 賦值給變量 b,因?yàn)?b 的類型是 number,而 a 是數(shù)字字面量類型 5,數(shù)字字面量類型是數(shù)字類型的子類型,所以賦值是允許的。

      需要注意的是,只有字面量類型才可以賦值給相應(yīng)的數(shù)值類型,普通數(shù)值類型不能賦值給字面量類型,除非兩者完全匹配。

      1.3. 枚舉類型可以賦值給數(shù)字類型

      枚舉類型在 TypeScript 中被編譯成了一個(gè)具有反向映射的對(duì)象。默認(rèn)情況下,枚舉類型的成員值是從 0 開始遞增的數(shù)字。由于枚舉成員值是數(shù)字類型,所以它們可以被賦值給數(shù)字類型。

      在上述示例中,將 Direction.Right 賦值給了枚舉類型的變量 direction,然后又將 direction 賦值給了數(shù)字類型的變量 num,此時(shí) num 的值為 1,與 Direction.Right 對(duì)應(yīng)的枚舉成員值相同。

      需要注意的是,枚舉類型不僅可以賦值給數(shù)字類型,也可以賦值給字面量類型或其他兼容的類型。這主要是由于 TypeScript 在類型系統(tǒng)中對(duì)枚舉類型進(jìn)行了特殊處理,使得枚舉成員值可以被當(dāng)作相應(yīng)的字面量值使用。

      2. 對(duì)象類型的兼容性

      對(duì)象類型包括接口(interface)、類(class)、字面量對(duì)象等。

      記住這句話:成員多的可以賦值給成員少的。

      2.1. 成員個(gè)數(shù)的兼容性

      對(duì)象類型 T 能夠賦值給對(duì)象類型 U,需要滿足的條件是 T 中的成員個(gè)數(shù)要大于等于 U 中的成員個(gè)數(shù)。也就是說(shuō),T 可以擁有 U 中的所有成員,但 T 可能還有額外的成員。

      在上述示例中,類 Point2D 具有 x 和 y 成員,類 Point3D 比類 Point2D 多了一個(gè) z 成員,根據(jù)兼容性規(guī)則,Point3D 可以賦值給 Point2D,因?yàn)轭?Point3D 擁有類 Point2D 中的所有成員。

      2.2. 成員類型的兼容性

      對(duì)象類型 T 能夠賦值給對(duì)象類型 U,需要滿足的條件是 T 中的每個(gè)成員的類型都能夠賦值給 U 中對(duì)應(yīng)成員的類型。這個(gè)規(guī)則適用于成員變量和成員函數(shù)。

      2.3. 可選屬性的兼容性

      對(duì)象類型 T 能夠賦值給對(duì)象類型 U,如果 U 中定義了可選屬性,且 T 中沒(méi)有對(duì)應(yīng)的屬性,則仍然可以進(jìn)行賦值。

      3. 函數(shù)類型兼容性

      函數(shù)之間的兼容性會(huì)比較復(fù)雜,需要考慮以下幾個(gè)方面:

      • 參數(shù)個(gè)數(shù)
      • 參數(shù)類型
      • 返回值類型
      3.1. 參數(shù)個(gè)數(shù)

      源函數(shù)的參數(shù)個(gè)數(shù)要小于等于目標(biāo)函數(shù)的參數(shù)個(gè)數(shù)。也就是說(shuō),源函數(shù)可以接受更少的參數(shù)或與目標(biāo)函數(shù)相同數(shù)量的參數(shù)。多余的參數(shù)是允許的,因?yàn)樵诤瘮?shù)調(diào)用時(shí)可以忽略它們。

      記住這句話:參數(shù)少的可以賦值給參數(shù)多的。

      在上述示例中,我們定義了兩個(gè)類型 Adder 和 Calculator 分別表示加法函數(shù)和計(jì)算函數(shù)。根據(jù)函數(shù)兼容性規(guī)則,add 可以賦值給 calculate,因?yàn)?Adder 的參數(shù)個(gè)數(shù)(2個(gè))少于 Calculator 的參數(shù)個(gè)數(shù)(3個(gè))。但是相反的賦值會(huì)導(dǎo)致兼容性錯(cuò)誤,因?yàn)?Calculator 的參數(shù)個(gè)數(shù)(3個(gè))要多于 Adder 的參數(shù)個(gè)數(shù)(2個(gè))。

      3.2. 參數(shù)類型

      在上述示例中,函數(shù) x 的參數(shù)只有一個(gè) a,類型為 number,函數(shù) y 的參數(shù)有兩個(gè) a 和 b,類型分別為 number 和 string,x 可以賦值給 y,是因?yàn)?x 的每個(gè)參數(shù)都能在 y 里找到對(duì)應(yīng)類型的參數(shù)。 注意的是參數(shù)的名字相同與否無(wú)所謂,只看它們的類型。 而 y 不能賦值給 x,因?yàn)?y 有個(gè)必需的第二個(gè)參數(shù),但是 x 并沒(méi)有,所以不允許賦值。

      3.3. 返回值類型

      如果返回值類型是普通類型,此時(shí)函數(shù)的返回值類型要相同。

      如果返回值類型是對(duì)象類型,此時(shí)成員多的可以賦值給成員少的。

      4. 類類型兼容性

      類與對(duì)象字面量和接口差不多,但有一點(diǎn)不同:類有靜態(tài)部分和實(shí)例部分的類型。 比較兩個(gè)類類型的對(duì)象時(shí),只有實(shí)例的成員會(huì)被比較。 靜態(tài)成員和構(gòu)造函數(shù)不在比較的范圍內(nèi)。

      私有的和受保護(hù)的成員必須來(lái)自于相同的類或者父類的派生類。

      5. 泛型類型兼容性

      當(dāng)泛型類型沒(méi)有明確指定類型參數(shù)時(shí),它被認(rèn)為是一種特殊的兼容性形式,稱為類型參數(shù)的默認(rèn),即泛型函數(shù)或泛型類在沒(méi)有傳遞類型參數(shù)的情況下,它們的類型參數(shù)會(huì)被推導(dǎo)為any。此時(shí),泛型類型可以兼容任意類型,也能賦值給其他泛型類型。

      當(dāng)泛型類型明確指定了類型參數(shù)時(shí),要求類型參數(shù)具有兼容的類型。這意味著泛型類型在傳遞不同類型參數(shù)時(shí),需要確保它們之間滿足兼容性規(guī)則。

      十一、交叉類型(Intersection Types)

      交叉類型類似于接口繼承,是將多個(gè)類型合并為一個(gè)類型。 也就是說(shuō)我們可以把現(xiàn)有的多種類型疊加到一起成為一種類型,它包含了所需的所有類型的特性。

      使用符號(hào)( & )來(lái)定義交叉類型。

      1. 組合對(duì)象類型

      在上述示例中,我們定義了 User 和 Admin 兩個(gè)類型,然后使用交叉類型 & 將 User & Admin 連接起來(lái)創(chuàng)建了一個(gè)新的類型 UserAdmin,該類型包含了 User 和 Admin 類型的所有成員,接著我們定義了一個(gè)變量 userAdmin,該變量同時(shí)具有 User 和 Admin 類型的屬性和方法。

      2. 合并函數(shù)類型

      在上述示例中,我們定義了兩個(gè)函數(shù)類型 AddFunc 和 MultiplyFunc,AddFunc 里面定義了 fn 函數(shù),MultiplyFunc 里面定義了 fn1 函數(shù),并使用交叉類型 & 將 AddFunc & MultiplyFunc 連接起來(lái)創(chuàng)建了一個(gè)新的類型 MathOperations。此時(shí)變量 mathOps 同時(shí)擁有 fn 和 fn1 兩個(gè)方法。

      3. 交叉類型VS接口繼承
      • 相同點(diǎn):都可以實(shí)現(xiàn)對(duì)象類型的組合。
      • 不同點(diǎn):兩種方式實(shí)現(xiàn)類型組合時(shí),對(duì)于同名屬性之間,處理類型沖突的方式不同。

      下面是接口繼承的示例,接口B繼承接口A,兩個(gè)接口都定義了 fn 方法,返回值都是 string 類型,但是參數(shù)的類型不同,一個(gè) string,一個(gè) number,由于 fn 參數(shù) value 的類型不兼容,所以接口 B 不能繼承接口 A。

      下面是交叉類型的示例:我們定義了 A 和 B 兩個(gè)接口,然后使用交叉類型 & 將 A & B 連接起來(lái)創(chuàng)建了一個(gè)新的類型 ,接著我們定義了一個(gè)變量 c,類型為 C,變量 c 調(diào)用 fn 方法,此時(shí)參數(shù)的類型我們可以傳數(shù)字類型或者字符串類型。

      4. 注意

      如果合并的多個(gè)接口類型存在同名屬性會(huì)是什么效果呢?

      在上面示例中,定義了兩個(gè)類型 User 和 Admin,其中類型 User 中有 id 和 name 屬性,類型 Admin 中有 name 和 age 屬性,兩個(gè)類型都有同名的 name 屬性,但類型不同,一個(gè)是 string,一個(gè)是 number,合并后,name 屬性的類型就是 string 和 number 兩個(gè)原子類型的交叉類型,即 never。

      此時(shí),我們?nèi)绻x予 user 任意類型的 name 屬性值都會(huì)提示類型錯(cuò)誤。而如果我們不設(shè)置 name 屬性,又會(huì)提示一個(gè)缺少必選的 name 屬性的錯(cuò)誤。在這種情況下,就意味著上述代碼中交叉出來(lái)的 UserAdmin 類型是一個(gè)無(wú)用類型。

      如果同名屬性的類型兼容,比如一個(gè)是 number,另一個(gè)是 number 的子類型、數(shù)字字面量類型,合并后 name 屬性的類型就是兩者中的子類型。

      在上面示例中,name 屬性的類型就是數(shù)字字面量類型 2,因此,我們不能把任何非 2 之外的值賦予 name 屬性。

      如果交叉類型中的某個(gè)成員是對(duì)象類型,那么交叉后的類型將擁有這些對(duì)象類型的所有屬性

      十二、泛型(Generics)1. 什么是泛型

      泛型(Generics)是 TypeScript 中一種允許我們?cè)诙x函數(shù)、類或接口時(shí)使用參數(shù)化類型的機(jī)制。泛型可以看作是類型參數(shù),類似于函數(shù)中的參數(shù),但是用于表示類型而不是值。它允許我們?cè)诙x函數(shù)、類或接口時(shí)使用占位符表示類型,并在實(shí)際使用時(shí)指定具體的類型。

      2. 一個(gè)簡(jiǎn)單的例子

      現(xiàn)在我們有個(gè)需求:實(shí)現(xiàn)一個(gè)函數(shù),傳入的函數(shù)參數(shù)是什么類型的,返回值的類型也要跟函數(shù)參數(shù)的類型相同,并且函數(shù)只能接收一個(gè)參數(shù),你會(huì)怎么做?

      上面的示例中,我們創(chuàng)建了一個(gè) identity 函數(shù),參數(shù)值和返回值類型都為 number,調(diào)用 identity 函數(shù),傳入一個(gè)數(shù)字,會(huì)返回?cái)?shù)字本身。但是,該函數(shù)只能接收數(shù)值類型,如果我調(diào)用函數(shù)的時(shí)候傳入字符串或者布爾值類型的值,此時(shí)就會(huì)報(bào)錯(cuò)。

      為了讓函數(shù)能夠接收任意類型,可以將參數(shù)類型改為any,但是,這樣就失去了 TS 的類型保護(hù),類型不安全。

      為了解決上面的這些問(wèn)題,我們使用泛型對(duì)上面的代碼進(jìn)行重構(gòu)。 泛型在保證類型安全(不丟失類型信息)的同時(shí),可以讓函數(shù)等于多鐘不同的類型一起工作,靈活可復(fù)用。

      上面示例中,我們?cè)诤瘮?shù)名 identity 后添加了 ,其中 T 代表 Type,在定義泛型時(shí)通常用作第一個(gè)類型變量名稱。但實(shí)際上 T 可以用任何有效名稱代替。在調(diào)用函數(shù) identity 時(shí),在<>中指定類型 string,此時(shí)參數(shù)和返回值類型也都為 string。

      3. 泛型語(yǔ)法
      • 在函數(shù)名稱的后面添加尖括號(hào)( <> ),尖括號(hào)中添加類型變量,比如下圖中的 T。
      • 其中 T 代表 Type,可以是任意合法的變量名稱。
      • 類型變量 T,是一種特殊類型的變量,它用于處理類型而不是值。
      • 該類型變量相當(dāng)于一個(gè)類型容器,能夠捕獲用戶提供的類型(具體是什么類型,由用戶調(diào)用該函數(shù)時(shí)指定)。
      • 因?yàn)?T 是類型,因此可以將其作為函數(shù)參數(shù)和返回值的類型,表示參數(shù)和返回值具有相同的類型。

      在下面的示例中,調(diào)用泛型函數(shù) identity,當(dāng)傳入類型 number 后,這個(gè)類型就會(huì)被函數(shù)聲明時(shí)指定的類型變量 T 捕獲到,此時(shí),T 的類型就是 number,所以,函數(shù) identity 的參數(shù)和返回值的類型也都是 number。

      4. 簡(jiǎn)化調(diào)用泛型函數(shù)
      • 在調(diào)用泛型函數(shù)時(shí),可以省略<類型>來(lái)簡(jiǎn)化泛型函數(shù)的調(diào)用。
      • 此時(shí),TS 內(nèi)部會(huì)采用一種叫做類型參數(shù)推斷的機(jī)制,來(lái)根據(jù)傳入的實(shí)參自動(dòng)推斷出類型變量 T 的類型。
      • 當(dāng)編譯器無(wú)法推斷類型或者推斷的類型不準(zhǔn)確時(shí),就需要顯示地傳入類型參數(shù)。

      比如,傳入實(shí)參10,TS 會(huì)自動(dòng)推斷出變量 num 的類型 number,并作為 T 的類型。

      5. 多個(gè)類型參數(shù)

      定義泛型的時(shí)候,可以一次定義多個(gè)類型參數(shù):

      上述示例中,我們定義了一個(gè) swap 函數(shù),用來(lái)交換輸入的元組。

      6. 泛型類

      泛型類(Generic Class)是指在定義類時(shí)使用泛型類型參數(shù)的類。它允許我們?cè)陬惖膶傩浴⒎椒ā?gòu)造函數(shù)以及實(shí)例化時(shí)使用泛型。

      • 在 class 名稱后面添加 <類型變量> ,這個(gè)類就變成了泛型類。
      • 在創(chuàng)建 class 實(shí)例時(shí),在類名后面通過(guò) <類型> 來(lái)指定明確的類型。

      下面是一個(gè)簡(jiǎn)單的泛型類的示例:

      7. 泛型接口
      • 在接口名稱的后面添加 <類型變量> ,那么,這個(gè)接口就變成了泛型接口。
      • 接口的類型變量,對(duì)接口中所有其它成員可見,也就是接口中所有成員都可以使用類型變量。
      • 使用泛型接口時(shí),需要顯示指定具體的類型。

      下面是一個(gè)簡(jiǎn)單的泛型接口的示例:

      8. 泛型參數(shù)的默認(rèn)類型

      在 TypeScript 2.3 以后,我們可以為泛型中的類型參數(shù)指定默認(rèn)類型。當(dāng)使用泛型時(shí)沒(méi)有在代碼中直接指定類型參數(shù),從實(shí)際值參數(shù)中也無(wú)法推測(cè)出時(shí),這個(gè)默認(rèn)類型就會(huì)起作用。

      9. 泛型約束

      默認(rèn)情況下,泛型函數(shù)的類型參數(shù) T 理論上是可以是任何類型的,不同于 any,你不管使用它的什么屬性或者方法都會(huì)報(bào)錯(cuò)(除非這個(gè)屬性和方法是所有集合共有的)。

      比如下面的示例中,我想打印出參數(shù)的 length 屬性,如果不進(jìn)行泛型約束 TS 是會(huì)報(bào)錯(cuò)的:類型“T”上不存在屬性“l(fā)ength”。

      報(bào)錯(cuò)的原因很明顯,如果要解決這個(gè)問(wèn)題,我們就可以通過(guò)給泛型(類型變量)添加約束。

      下面我們通過(guò) extends 關(guān)鍵字進(jìn)行類型約束:

      在上述示例中,我們定義了一個(gè) ILength 接口,具有 length 屬性。在泛型函數(shù) getLength 中,使用 T extends ILength 進(jìn)行約束,該約束表示:傳入的類型必須具有 length 屬性。

      十三、TS中的關(guān)鍵字

      TS 內(nèi)置了一些常用的工具類型,來(lái)簡(jiǎn)化 TS 中一些常見的操作,它們都是基于泛型實(shí)現(xiàn)的,并且是內(nèi)置的,所以可以直接使用。

      在學(xué)習(xí)工具類型之前,我們先學(xué)習(xí)一些關(guān)鍵字和基礎(chǔ)知識(shí),以便我們可以更好的去學(xué)習(xí)后面的內(nèi)置工具類型。

      1. keyof

      在 TS 中,keyof 操作符主要用途是用于獲取類型中所有鍵的關(guān)鍵字。它用于泛型中,通常與索引類型(index type)結(jié)合使用。其返回類型是聯(lián)合類型。

      下面示例中,我們定義了一個(gè)接口 Person,包含 name、age 和 gender 三個(gè)鍵,然后使用 keyof 來(lái)獲取 Person 接口的所有鍵,這樣,Keys 類型就是一個(gè)由 &34;name&34; | &34;age&34; | &34;gender&34; 構(gòu)成的聯(lián)合字面量類型。

      下面示例中,我們創(chuàng)建一個(gè)函數(shù)來(lái)獲取對(duì)象中屬性的值:

      在 TS 中, 是一種泛型約束方式,用于限制一個(gè)泛型類型參數(shù) key 的范圍。extends 關(guān)鍵字表示限制 key 的取值只能是 Type 類型中已有的屬性名。可以理解為:Key 只能是 Type 所有鍵中的任意一個(gè),或者說(shuō)只能訪問(wèn)對(duì)象中存在的屬性。

      在上面的例子中,getProp 函數(shù)接收兩個(gè)參數(shù):一個(gè)泛型類型參數(shù) Type,代表輸入對(duì)象的類型;一個(gè)泛型類型參數(shù) Key,代表屬性名的類型。keyof Type 實(shí)際上獲取的是 person 對(duì)象所有鍵的聯(lián)合字面量類型,也就是:&39;name&39; | &39;age&39; | &39;gender&39;,當(dāng)我們調(diào)用調(diào)用 getProp 函數(shù)傳入一個(gè)不存在的屬性名,例如: &39;school&39; 會(huì)引發(fā)編譯錯(cuò)誤。

      2. typeof

      在 TS 中,typeof 操作符的主要用途是在類型上下文中獲取變量或者屬性的類型。

      2.1. typeof獲取變量的聲明類型

      在 TS 中,typeof 可以用來(lái)返回一個(gè)變量的聲明類型,如果不存在,則獲取該類型的推論類型。

      需要注意的是:

      • typeof作為類型操作符后面只能跟變量。
      • 如果變量沒(méi)有聲明類型,typeof返回變量的推斷類型。

      如果變量沒(méi)有明確聲明類型,typeof 將返回變量的推斷類型。此時(shí),let關(guān)鍵字聲明的變量,可以被重新賦值。

      有時(shí)候,我們希望變量是常量,不允許被重新賦值。const 關(guān)鍵字可以解決這個(gè)問(wèn)題。此時(shí),基于類型推斷,返回類型是等號(hào)右邊的字面量類型。

      例如,下面示例中,typeof str 返回的是字面量類型 &39;Echo&39;,不是字符串。

      在 Typescript3.4 中引入了一種新的字面量構(gòu)造方式,const 斷言。在 const 斷言作用下,即使是 let 聲明也可以限制類型擴(kuò)展,變量不能被重新賦值。

      例如,下面示例中,typeof str 返回的是字面量類型 &39;Echo&39;,不是字符串。

      當(dāng)我們使用 const 斷言構(gòu)造新的字面量表達(dá)式時(shí),應(yīng)注意以下幾點(diǎn):

      • 表達(dá)式中的任何字面量類型都不應(yīng)該被擴(kuò)展。
      • 對(duì)象字面量的屬性,將使用 readonly 修飾。
      • 數(shù)組字面量將變成 readonly 元組。

      如果變量明確聲明了類型,推斷類型不受 const 影響,typeof str 返回 str 的聲明類型 string,而不是字面量類型 &34;Steven&34;,但是變量依然不能被重新賦值。

      2.2. typeof與對(duì)象結(jié)合使用

      typeof與對(duì)象結(jié)合使用,可以用來(lái)獲取對(duì)象的結(jié)構(gòu)類型,以及使用該類型來(lái)聲明新的變量或函數(shù)參數(shù)等。

      1. 獲取對(duì)象的類型

      在上述示例中,typeof person 返回的是對(duì)象 person 的類型,即 { name: string; age: number; }。

      1. 聲明新變量的類型為對(duì)象的類型

      在上述示例中,我們使用 typeof person 將 newPerson 的類型聲明為 { name: string; age: number; },并賦予了新的值。

      1. 在函數(shù)參數(shù)中使用對(duì)象的類型

      在上述示例中,函數(shù) printObj 接收一個(gè)參數(shù),其類型為 typeof person,即接收與對(duì)象 person 相同類型的參數(shù)。

      需要注意的是,typeof 運(yùn)算符用于獲取對(duì)象類型是在靜態(tài)類型檢查階段進(jìn)行的,而不是在運(yùn)行時(shí)期執(zhí)行的。因此,它只提供了類型信息,而不會(huì)直接訪問(wèn)對(duì)象的值。

      2.3. typeof與接口結(jié)合使用

      typeof 與接口結(jié)合使用可以用于創(chuàng)建新類型,該類型的屬性和方法將與給定對(duì)象類型保持一致。

      在上述實(shí)例中,定義了一個(gè)名為 Person 的接口,然后創(chuàng)建一個(gè)對(duì)象 person,類型為 Person,接著使用 typeof 來(lái)創(chuàng)建一個(gè)新的類型 NewPerson,該類型的屬性和方法將與 Person 接口中定義的屬性和方法保持一致,這樣我們就可以基于 NewPerson 來(lái)創(chuàng)建新的對(duì)象。

      需要注意的是,typeof 運(yùn)算符與接口結(jié)合使用通常適用于已存在的對(duì)象,它提取已知對(duì)象的類型用于創(chuàng)建新的類型。它不會(huì)用于動(dòng)態(tài)創(chuàng)建對(duì)象或?qū)嵗悺?/p>2.4. typeof與keyof結(jié)合使用

      keyof 主要用于獲取類型的所有屬性鍵,可以與 typeof 結(jié)合使用,獲取某個(gè)類型的鍵集合。

      3. in

      在 TS 中,in 操作符的主要用于遍歷目標(biāo)類型的屬性 key 值。類似 for...in,一般結(jié)合 [] 一起使用。

      3.1. 遍歷枚舉類型

      3.2. 遍歷聯(lián)合類型

      4. extends4.1. 用于泛型函數(shù)

      4.2. 用于泛型類

      4.3. 用于類繼承

      4.4. 用于繼承接口

      4.5. 用于類型約束

      4.6. 用于條件類型

      TypeScript 2.8引入了條件類型表達(dá)式,類似于三元運(yùn)算符。

      條件類型也支持嵌套。

      十四、泛型工具類型

      泛型工具類型這一章節(jié)相關(guān)的內(nèi)容我想放到其它文章中來(lái)講,因?yàn)檫@里涉及到的知識(shí)點(diǎn)有點(diǎn)多,一時(shí)半會(huì)寫不完,大家可以持續(xù)關(guān)注我,精力有限,盡量做到每周23更!!!

      十五、總結(jié)

      如果文章有什么錯(cuò)誤,歡迎大家在評(píng)論區(qū)指正,如果覺得本文對(duì)您有幫助的話,歡迎關(guān)注點(diǎn)贊收藏哦~

      原文鏈接:https://juejin.cn/post/7276630249548005415

      主站蜘蛛池模板: 中国美女一级片| 色综合天天综合网国产| 亚洲成h人av无码动漫无遮挡| 亚洲国产精品电影| 最近更新中文字幕| 国产亚洲欧美在线观看| 亚洲成本人无码薄码区| 日本黄色一区二区三区| 国产成人精品二区三区亚瑟| 国产国语熟妇视频在线观看| 一区二区三区毛aaaa片特级 | 国产精品久久久久久婷婷| 色香蕉色香蕉在线视频| 国产精品爽| 无码成人午夜在线观看| 欧美牲交a欧美牲交vdo18| 久久一区| 国产8区| 69天堂人成无码免费视频| 亚洲国产高清aⅴ视频| 丁香六月综合| 男人女人拔萝卜视频| 久久婷婷成人综合色综合| 精品国产美女福利在线不卡| 亚洲天堂影视| 亚洲人成小说网站色在线| 日韩欧美在线免费观看| 人人妻人人澡人人爽欧美一区双| 国产爆乳成av人在线播放| 国产精品电影一区二区三区| 成人国产精品日本在线观看| 日韩人妻无码一区二区三区综合| 三级在线视频| 青草91| 亚洲综合天堂一区二区三区 | 好吊色在线视频| 国内精品久久久久影院蜜芽| 国产成人精品免高潮在线观看| 精品人妻潮喷久久久又裸又黄| 午夜免费在线| 欧美日韩精品在线播放|