<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>

          TS實用技巧,3分鐘搞懂 unknown 和 never!

          共 4448字,需瀏覽 9分鐘

           ·

          2021-08-29 21:55


          字?jǐn)?shù):1737字   閱讀: 3 分鐘

          大家好,今天和大家聊下讓我曾經(jīng)迷惑的兩個TS類型:unknown 和 never,不知道大家有沒有對其用法有所迷惑呢,好記性比不過爛筆頭,為了讓我不再迷惑,還是通過文字的形式整理下加深下印象比較靠譜,希望今天的分享能給大家解惑。

          一、unknown 類型

          unknown 類型是 TS3 新增的類型,這個類型與 any 類型類似,可以設(shè)置任何的類型值,隨后可以更改類型。因此,我們可以將變量先設(shè)置為字符串類型,然后再將其設(shè)置為數(shù)字類型,如果事先不檢查類型,使用any類型,調(diào)用了不存在的方法,編譯時不會報錯,代碼運行時才會發(fā)現(xiàn)錯誤。但是使用unknown 類型不一樣,如果不進行類型判斷,執(zhí)行相關(guān)操作編譯器就會報錯。文字說了這么多,還是 上代碼,更容易理解些。

          1、關(guān)于 Any 的問題

          首先我們創(chuàng)建一個 any.ts 的文件,代碼如下:

          let val: any = 22;
          val = "string value";
          val = new Array();
          val.push(33);
          console.log(val);

          運行編譯后的代碼,并不會報錯,也是按照我們的預(yù)期輸出:[33]

          由于是 any 類型,我們可以隨意更改類型,當(dāng)變成數(shù)組類型時,我們調(diào)用push方法進行內(nèi)容操作,看似沒啥問題,如果我們開發(fā)人員,由于疏忽,打錯了一個不存在的方法,ts代碼能正常編譯,幫我們發(fā)現(xiàn)問題嗎?

          let val: any = 22;
          val = "string value";
          val = new Array();
          val.doesnotexist(33);
          console.log(val);

          當(dāng)運行 tsc any 命令后,你會發(fā)現(xiàn)編譯器能順利編譯,當(dāng)我們運行 node any,編譯后的代碼能正常執(zhí)行嗎?答案是顯而易見的,會報異常,你會在控制臺發(fā)現(xiàn)以下錯誤:

          val.doesnotexist(33);
              ^

          TypeError: val.doesnotexist is not a function

          上述的錯誤,大家可能不會犯,但是項目大時,參與的人多時,就很難避免這樣類似的問題,因此unknown 類型出現(xiàn)了。

          2、一段 unknown 類型的代碼

          接下來我們來看看它是怎么解決類似的問題,我們還是從一段簡單的代碼開始,如下段代碼所示:

          let val: unknown = 22;
          val = "string value";
          val = new Array();
          val.push(33);
          console.log(val);

          當(dāng)你編譯此代碼時,你會立馬收到如下報錯:

          Property 'push' does not exist on type 'unknown'.

          是不是很奇怪,雖然我們將其類型更改為數(shù)組類型,但是編譯器不認(rèn)識,它認(rèn)為unknown類型,這個類型沒有push方法,當(dāng)然會報錯,除非先判斷類型,如果是相關(guān)類型且正確執(zhí)行相關(guān)方法,編譯器則會順利通過,如下段代碼所示

          let val: unknown = 22;
          val = "string value";
          val = new Array();
          if (val instanceof Array) {
              val.push(33);
          }
          console.log(val);

          雖然有些麻煩,但是相比 any 類型說,更加安全,在代碼編譯期間,就能幫我們發(fā)現(xiàn)由于類型造成的問題,因此在大多的場景,建議使用 unknown 類型替代 any。

          二、never 類型

          這個類型看起來有些奇怪,乍一看,看起來和void相似,但是其完全不一樣。從字面意思上來說,表示一個從來不會有返回值的函數(shù)(例:while(true) {}),一個總是會拋出錯誤的函數(shù)(function foo() { throw new Error('Not Implemented') })。那么問題來了,它和 void 類型啥區(qū)別,void 表示沒有任何類型,函數(shù)沒有返回值時(可以返回,但是沒值),我們可以設(shè)置為void 類型;never這不一樣,一個函數(shù)根本就沒返回(或者總是出錯,永遠不會有返回值)??次淖钟行┵M勁,我們還是來看一段簡單的代碼來理解下吧,如下所示:

          function alwaysThrows(): never 
              throw "this will always throw"
              return -1
          }

          當(dāng)我們編譯上述代碼時,編譯器就會報錯,如下所示:

          Type 'number' is not assignable to type 'never'.

          編譯器已經(jīng)很明確的告訴了我們 never 類型不應(yīng)該返回任何值(或拋異常)。那么問題來了,這個類型有啥用呢?我們還是舉個例子來理解下吧,比如你有個 enum 枚舉類型,代碼如下所示:

          enum TestNeverEnum { 
              FIRST, 
              SECOND 
          }

          在 switch 當(dāng)中判斷 type,TS 是可以收窄類型的 (discriminated union):

          enum TestNeverEnum {
              FIRST,
              SECOND
          }

          function getEnumValue(value: TestNeverEnum): string 
              switch (value) { 
                  // 這里 value 被收窄為 TestNeverEnum.FIRST
                  case TestNeverEnum.FIRST: return "First case"
                  // 這里 value 被收窄為 TestNeverEnum.SECOND
                  case TestNeverEnum.SECOND: return "Second case"
                  // returnValue 是 never 類型
                  defaultconst returnValue: never = value; 
              } 
          }

          注意在 default 里面我們把被收窄為 never 的 returnValue 賦值給一個顯式聲明為 never 的變量。如果一切邏輯正確,那么這里應(yīng)該能夠編譯通過。但是假如有一天你的同事增加了TestNeverEnum 枚舉類型:

          enum TestNeverEnum {
              FIRST,
              SECOND,
              THIRD
          }

          然而他忘記了在 getEnumValue 里面加上針對 THIRD 的處理邏輯,這個時候在 default branch 里面 returnValue 會被收窄為 TestNeverEnum.THIRD,導(dǎo)致無法賦值給 never(因為有值返回),產(chǎn)生一個編譯錯誤。編譯器會產(chǎn)生如下的錯誤:

          Type 'TestNeverEnum' is not assignable to type 'never'.

          所以通過這個辦法,你可以確保 getEnumValue 方法里總是窮盡 (TestNeverEnum) 了所有 All 的可能類型,目的就是寫出類型絕對安全的代碼。

          三、結(jié)束語

          今天的內(nèi)容就到這里,這兩個類型你品明白了嗎?雖然內(nèi)容不多,但是需要細(xì)品 ,才能理解其應(yīng)用場景和用好他們,感謝的閱讀。

          最后



          如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:

          1. 點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-)

          2. 歡迎加我微信「 sherlocked_93 」拉你進技術(shù)群,長期交流學(xué)習(xí)...

          3. 關(guān)注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。


          點個在看支持我吧,轉(zhuǎn)發(fā)就更好了



          瀏覽 282
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  无码黄色电影 | 男女拍拍拍拍 | 久久久久久久久久夜夜想 | 涩小说校园春色图片区视频区小说区 | PP特极毛片 |