<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ypeScript-泛型-1-概念,泛型接口和泛型類

          共 5900字,需瀏覽 12分鐘

           ·

          2021-08-12 18:29

          ?

          鬼哥本周將通過幾篇優(yōu)秀的Typescript文章,讓大家學(xué)習(xí)到Typescript一些高級的用法,讓大家對Typescript更加的深入理解,并且更好實(shí)踐到工作當(dāng)中,【一共五篇文章】,關(guān)注我們一起完成這個(gè)系列的學(xué)習(xí)

          原文:https://github.com/leslie1943

          ?


          ?? 泛型是什么?

          ?

          軟件工程中,我們不僅要創(chuàng)建一致的定義良好的 API,同時(shí)也要考慮可重用性. 組件不僅能夠支持當(dāng)前的數(shù)據(jù)類型,同時(shí)也能支持未來的數(shù)據(jù)類型,這在創(chuàng)建大型系統(tǒng)時(shí)為你提供了十分靈活的功能.

          ?
          • 在像 C# 和 Java 這樣的語言中, 可以使用泛型來創(chuàng)建可重用的組件, 一個(gè)組件可以支持多種類型的數(shù)據(jù). 這樣用戶就可以以自己的數(shù)據(jù)類型來使用組件.
          • 設(shè)計(jì)泛型的關(guān)鍵目的在成員之間提供有意義的約束, 這些成員可以是: 類的實(shí)例成員, 類的方法, 函數(shù)參數(shù) 和 函數(shù)返回值
          • 為了便于大家更好地理解上述的內(nèi)容, 我們來舉個(gè)例子, 在這個(gè)例子中, 我們將一步步揭示泛型的作用.
          ?

          首先我們來定義一個(gè)通用的 identity 函數(shù), 該函數(shù)接收一個(gè)參數(shù)并直接返回它:

          ?
          function identity(value{
            return value
          }
          console.info(identity(1)) // 1
          • 現(xiàn)在, 我們將 identity 函數(shù)做適當(dāng)?shù)恼{(diào)整, 以支持 TypeScript 的 Number 類型的參數(shù):
          function identity(value: Number): Number {
            return value
          }
          console.info(identity(1)) // 1
          • 這里 identity 的問題是我們將 Number 類型分配給參數(shù)和返回類型, 使該函數(shù)僅可用于該原始類型. 但該函數(shù)并不是可擴(kuò)展或通用的, 很明顯這并不是我們所希望的.
          • 我們確實(shí)可以把 Number 換成 any, 我們失去了定義應(yīng)該返回哪種類型的能力, 并且在這個(gè)過程中使編譯器失去了類型保護(hù)的作用. 我們的目標(biāo)是讓 identity 函數(shù)可以適用于任何特定的類型, 為了實(shí)現(xiàn)這個(gè)目標(biāo), 我們可以使用泛型來解決這個(gè)問題, 具體實(shí)現(xiàn)方式如下
          // ?????? Step - 3
          function identity3<T>(value: T): T {
            return value

          • 對于剛接觸 TypeScript 泛型的讀者來說, 首次看到 語法會感到陌生. 但這沒什么可擔(dān)心的, 就像傳遞參數(shù)一樣, 我們傳遞了我們想要用于特定函數(shù)調(diào)用的類型.

          • 當(dāng)我們調(diào)用identity<Number>(1),Number類型就像參數(shù)1一樣, 它將出現(xiàn)在T的任何位置填充該類型. 圖中<T>內(nèi)部的T被稱為類型變量, 它是我們希望傳遞給identity函數(shù)的類型占位符. 同時(shí)它被分配給value參數(shù)用來代替它的類型, 此時(shí) T充當(dāng)?shù)氖穷愋? 而不是特定的Number類型

          • 其中T代表Type, 在定義泛型時(shí)通常用作第一個(gè)類型變量名稱. 但實(shí)際上T可以用做任何有效名稱代替, 除了T之外,以下是常見泛型變量代表的意思

          • K(Key): 表示對象中的鍵類型

          • V(Value): 表示對象中的值類型

          • E(Element): 表示元素類型

          • 其實(shí)并不是只能定義一個(gè)類型變量, 我們可以引入希望定義的任何數(shù)量的類型變量. 比如我們引入一個(gè)新的類型變量U, 用于擴(kuò)展定義我們的identity函數(shù)

          function identity4<TU>(value: T, message: U): T {
            console.info(message)
            return value
          }
          console.log(identity4<Numberstring>(68'Semlinker'))
          • 除了為類型變量顯式設(shè)定值之外, 一種更常見的做法是使編譯器自動選擇這些類型, 從而使代碼更簡潔. 我們可以完全省略尖括號, 比如:
          function identity5<TU>(value: T, message: U): T {
            console.info(message)
            return value
          }
          console.log(identity5(68'Semlinker'))
          • 對于上述代碼, 編譯器足夠聰明, 能夠知道我們的參數(shù)類型, 并將它們賦值給 T 和 U, 而不需要開發(fā)人員顯式指定它們. 如你所見, 該函數(shù)接收你傳遞給它的任何類型, 使得我們可以為不同類型創(chuàng)建可重用的組件. 現(xiàn)在我們再來看一下 identity 函數(shù):
          function identity <TU>(value: T, message: U) : T {
            console.log(message);
            return value;
          }
          • 相比之前定義的 identity 函數(shù), 新的 identity 函數(shù)增加了一個(gè)類型變量 U, 但該函數(shù)的返回類型我們?nèi)匀皇褂?T. 如果我們想要返回兩種類型的對象該怎么辦呢?針對這個(gè)問題, 我們有多種方案, 其中一種就是使用元組, 即為元組設(shè)置通用的類型:
          function identity6<TU>(value: T, message: U): [TU{
            console.info(message)
            return [value, message]
          }
          console.log(identity6(68'Semlinker'))
          • 雖然使用元組解決了上述的問題, 但有沒有其它更好的方案呢?答案是有的, 你可以使用泛型接口

          ?? 泛型接口

          為了解決上面提到的問題, 首先讓我們創(chuàng)建一個(gè)用于的 identity 函數(shù)通用 Identities 接口:

          interface Identities<V, M> {
            value: V
            message: M
          }
          • 在上述的 Identities 接口中, 我們引入了類型變量 V 和 M, 來進(jìn)一步說明有效的字母都可以用于表示類型變量, 之后我們就可以將 Identities 接口作為 identity 函數(shù)的返回類型:
          interface Identities<V, M> {
            value: V
            message: M
          }

          function identity<TU>(value: T, message: U): Identities<TU{
            console.info(`${value}${typeof value}`)
            console.info(`${message}${typeof message}`)
            let identities: Identities<T, U> = {
              value,
              message,
            }
            return identities
          }
          console.info(identity<NumberString>(68'finder'))
          • 以上代碼成功運(yùn)行后, 在控制臺會輸出以下結(jié)果:
          // 68: number
          // Semlinker: string
          // {value: 68, message: "Semlinker"}

          ?? 泛型類

          在類中使用泛型也很簡單, 我們只需要在類名后面, 使用 <T, ...> 的語法定義任意多個(gè)類型變量, 具體示例如下:

          interface PersonInterface<U> {
            value: U
            getIdentity: () => U
          }

          class IdentityClass<T> implements PersonInterface<T> {
            value: T

            constructor(value: T) {
              this.value = value
            }

            getIdentity(): T {
              return this.value
            }
          }

          const p1 = new IdentityClass<string>('Leslie')
          console.info(`p1 value ${p1.value}`// p1 value Leslie
          console.info(`p1.getIdentity()  ${p1.getIdentity()}`// p1.getIdentity()  Leslie

          const p2 = new IdentityClass<number>(1943)
          console.info(`p2 value ${p2.value}`// p2 value 1943
          console.info(`p2.getIdentity()  ${p2.getIdentity()}`// p2.getIdentity()  1943

          我們看下實(shí)例化p1的調(diào)用過程

          • 在實(shí)例化IdentityClass的對象是, 我們傳入string類型和構(gòu)造函數(shù)參數(shù)值Leslie;

          • 之后在IdentityClass類中, 類型變量T的值變成String類型

          • IdentityClass類實(shí)現(xiàn)了PersonInterface<T>,而此時(shí)T表示String類型,因此等價(jià)于該類實(shí)現(xiàn)了PersonInterface<String>接口

          • 而對于PersonInterface<U>來說, 類型變量U變成了String. 這里有意使用不同的變量名, 以表明類型值沿鏈向上傳播, 且與變量名無關(guān).

          • 泛型類可確保在整個(gè)類中一致地使用指定的數(shù)據(jù)類型. 比如, 你可能已經(jīng)注意到在使用 Typescript 的 React 項(xiàng)目中使用了以下約定:

          type Props = {
            className?: string
             ...
          };

          type State = {
            submitted?: bool
             ...
          };
          class MyComponent extends React.Component<Props, State>{
            
          }
          • 在以上代碼中, 我們將泛型與 React 組件一起使用, 以確保組件的 props 和 state 是類型安全的.
          • 相信看到這里一些讀者會有疑問, 我們在什么時(shí)候需要使用泛型呢?通常在決定是否使用泛型時(shí), 我們有以下兩個(gè)參考標(biāo)準(zhǔn):
          • 當(dāng)函數(shù),接口或類將處理多種數(shù)據(jù)類型時(shí).
          • 當(dāng)函數(shù),接口或類在多個(gè)地方使用該數(shù)據(jù)類型時(shí).
          • 很有可能你沒有辦法保證在項(xiàng)目早期就使用泛型的組件, 但是隨著項(xiàng)目的發(fā)展, 組件的功能通常會被擴(kuò)展. 這種增加的可擴(kuò)展性最終很可能會滿足上述兩個(gè)條件, 在這種情況下, 引入泛型將比復(fù)制組件來滿足一系列數(shù)據(jù)類型更干凈.

          關(guān)注公眾號添加鬼哥微信,和鬼哥一起學(xué)習(xí)

          ?? 看完三件事

          如果你覺得這篇內(nèi)容對你挺有啟發(fā),不妨:

          • 點(diǎn)個(gè)【在看】,或者分享轉(zhuǎn)發(fā),讓更多的人也能看到這篇內(nèi)容

          • 點(diǎn)擊↓面關(guān)注我們,一起學(xué)前端

          • 長按↓面二維碼,添加鬼哥微信,一起學(xué)前端



          瀏覽 30
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧美日韩一区 | 无码在线免费视频 | 麻豆精品无码视频 | 在线黄网 | 超碰网站在线观看 |