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

          共 4278字,需瀏覽 9分鐘

           ·

          2021-03-03 02:18

          字數(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ù)組類型,但是編譯器不認識,它認為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ù)根本就沒返回(或者總是出錯,永遠不會有返回值)。看文字有些費勁,我們還是來看一段簡單的代碼來理解下吧,如下所示:

          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)容不多,但是需要細品 ,才能理解其應(yīng)用場景和用好他們,感謝的閱讀。


          瀏覽 82
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  国际毛片网| 一级性视频 | 3344在线观看免费视频 | 97国产成人 | 国产一区二区精品在线 |