TypeScript `unknown` 類型

<table class="d-block"> <tbody class="d-block"> <tr class="d-block"> <td class="d-block comment-body markdown-body js-comment-body rgh-linkified-code">html

<p><code>unknown</code> 字面理解和 <code>any</code> 其實沒差,任何類型均可賦值給它,但有一點,</p> <blockquote> <p>Anything is assignable to unknown, but unknown isn’t assignable to anything but itself and any without a type assertion or a control flow based narrowing</p> <p><em>--<a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html" rel="nofollow">TypeScript 3.0 Release notes - New unknown top type</a></em></p> </blockquote> <p><code>unknown</code> 類型不能賦值給除了 <code>unknown</code> 或 <code>any</code> 的其餘任何類型,使用前必需顯式進行指定類型,或是在有條件判斷狀況下可以隱式地進行類型推斷的狀況。</p> <p>下面代碼是合法的:</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">let</span> a<span class="pl-k">:</span> <span class="pl-c1">unknown</span>; <span class="pl-k"><span class="pl-k">const</span></span> b<span class="pl-k">:</span> <span class="pl-c1">unknown</span> <span class="pl-k">=</span> <span class="pl-smi">a</span>; <span class="pl-k"><span class="pl-k">const</span></span> c<span class="pl-k">:</span> <span class="pl-c1">any</span> <span class="pl-k">=</span> <span class="pl-smi">a</span>;</pre></div> <p>由於 <code>unknown</code> 是能夠賦值給 <code>unknown</code> 的,而下面的代碼則不行,</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">let</span> a<span class="pl-k">:</span> <span class="pl-c1">unknown</span>; <span class="pl-c"><span class="pl-c">//</span> 🚨Type 'unknown' is not assignable to type 'number'.ts(2322)</span> <span class="pl-k"><span class="pl-k">const</span></span> b<span class="pl-k">:</span> <span class="pl-c1">number</span> <span class="pl-k">=</span> <span class="pl-smi">a</span>;</pre></div> <p>可是若是使用時,明確知道了類型,則能夠這樣來修正:</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">let</span> a<span class="pl-k">:</span> <span class="pl-c1">unknown</span>; <span class="pl-c"><span class="pl-c">//</span> 🚨Type 'unknown' is not assignable to type 'number'.ts(2322)</span> <span class="pl-k"><span class="pl-k">const</span></span> b<span class="pl-k">:</span> <span class="pl-c1">number</span> <span class="pl-k">=</span> <span class="pl-smi">a</span>;</pre></div> <p>或者在條件語句中,已經能夠明確推斷出類型:</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">let</span> a<span class="pl-k">:</span> <span class="pl-c1">unknown</span>; <span class="pl-k">let</span> b<span class="pl-k">:</span> <span class="pl-c1">number</span> <span class="pl-k">=</span> &lt;<span class="pl-c1">number</span>&gt;<span class="pl-smi">a</span>;typescript

<span class="pl-k">function</span> isNumber(<span class="pl-v">val</span><span class="pl-k">:</span> <span class="pl-c1">any</span>)<span class="pl-k">:</span> <span class="pl-en">val</span> <span class="pl-k">is</span> <span class="pl-c1">number</span> { <span class="pl-k">return</span> <span class="pl-k">typeof</span> <span class="pl-smi">val</span> <span class="pl-k">===</span> <span class="pl-s"><span class="pl-pds">"</span>number<span class="pl-pds">"</span></span>; }安全

<span class="pl-k">if</span> (<span class="pl-en">isNumber</span>(<span class="pl-smi">a</span>)) { <span class="pl-smi">b</span> <span class="pl-k">=</span> <span class="pl-smi">a</span>; }</pre></div>markdown

<p>因此在使用時,<code>unknown</code> 類型會比 <code>any</code> 更加安全。這個安全體如今,雖然它和 <code>any</code> 同樣存儲了任意類型的值,可是具體使用的時候,這個類型須要顯式肯定,由使用者進行指定將 <code>unknown</code> 轉換成某一肯定類型。</p> <h2>優先級</h2> <h3>與正交類型的搭配</h3> <p>正交類型(intersection type)中,<code>unknown</code> 不起做用:</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">type</span> <span class="pl-en">T00</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">&amp;</span> <span class="pl-c1">null</span>; <span class="pl-c"><span class="pl-c">//</span> null</span> <span class="pl-k">type</span> <span class="pl-en">T01</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">&amp;</span> <span class="pl-c1">undefined</span>; <span class="pl-c"><span class="pl-c">//</span> undefined</span> <span class="pl-k">type</span> <span class="pl-en">T02</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">&amp;</span> <span class="pl-c1">null</span> <span class="pl-k">&amp;</span> <span class="pl-c1">undefined</span>; <span class="pl-c"><span class="pl-c">//</span> null &amp; undefined (which becomes never)</span> <span class="pl-k">type</span> <span class="pl-en">T03</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">&amp;</span> <span class="pl-c1">string</span>; <span class="pl-c"><span class="pl-c">//</span> string</span> <span class="pl-k">type</span> <span class="pl-en">T04</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">&amp;</span> <span class="pl-c1">string</span>[]; <span class="pl-c"><span class="pl-c">//</span> string[]</span> <span class="pl-k">type</span> <span class="pl-en">T05</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">&amp;</span> <span class="pl-c1">unknown</span>; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">type</span> <span class="pl-en">T06</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">&amp;</span> <span class="pl-c1">any</span>; <span class="pl-c"><span class="pl-c">//</span> any</span></pre></div> <h3>與聯合類型的搭配</h3> <p>聯合類型(union type)中 <code>unknown</code> 起絕對做用:</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">type</span> <span class="pl-en">T10</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">|</span> <span class="pl-c1">null</span>; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">type</span> <span class="pl-en">T11</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">|</span> <span class="pl-c1">undefined</span>; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">type</span> <span class="pl-en">T12</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">|</span> <span class="pl-c1">null</span> <span class="pl-k">|</span> <span class="pl-c1">undefined</span>; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">type</span> <span class="pl-en">T13</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">|</span> <span class="pl-c1">string</span>; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">type</span> <span class="pl-en">T14</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">|</span> <span class="pl-c1">string</span>[]; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">type</span> <span class="pl-en">T15</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">|</span> <span class="pl-c1">unknown</span>; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">type</span> <span class="pl-en">T16</span> <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">|</span> <span class="pl-c1">any</span>; <span class="pl-c"><span class="pl-c">//</span> any</span></pre></div> <p>上面僅一個例外,及和 <code>any</code> 組成的聯合類型,最終結果是 <code>any</code>。</p> <h3>使用在條件類型中</h3> <p>條件類型(conditional type)中,</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">type</span> <span class="pl-en">T30</span>&lt;<span class="pl-en">T</span>&gt; <span class="pl-k">=</span> <span class="pl-c1">unknown</span> <span class="pl-k">extends</span> <span class="pl-en">T</span> <span class="pl-k">?</span> <span class="pl-c1">true</span> <span class="pl-k">:</span> <span class="pl-c1">false</span>; <span class="pl-c"><span class="pl-c">//</span> Deferred</span> <span class="pl-k">type</span> <span class="pl-en">T31</span>&lt;<span class="pl-en">T</span>&gt; <span class="pl-k">=</span> <span class="pl-en">T</span> <span class="pl-k">extends</span> <span class="pl-c1">unknown</span> <span class="pl-k">?</span> <span class="pl-c1">true</span> <span class="pl-k">:</span> <span class="pl-c1">false</span>; <span class="pl-c"><span class="pl-c">//</span> Deferred (so it distributes)</span></pre></div> <p>對於上面的條件類型,進行如下測試:</p> <div class="highlight highlight-source-ts"><pre><span class="pl-c"><span class="pl-c">//</span> `unknown` 不能賦值給 `number`</span> <span class="pl-k">type</span> <span class="pl-en">foo</span> <span class="pl-k">=</span> <span class="pl-en">T30</span>&lt;<span class="pl-c1">number</span>&gt;; <span class="pl-c"><span class="pl-c">//</span> false</span> <span class="pl-c"><span class="pl-c">//</span> `unknown` 能夠賦值給 `any`</span> <span class="pl-k">type</span> <span class="pl-en">bar</span> <span class="pl-k">=</span> <span class="pl-en">T30</span>&lt;<span class="pl-c1">any</span>&gt;; <span class="pl-c"><span class="pl-c">//</span> true</span>測試

<span class="pl-c"><span class="pl-c">//</span> 任何類型均可賦值給 unknown,因此都爲 true</span> <span class="pl-k">type</span> <span class="pl-en">a</span> <span class="pl-k">=</span> <span class="pl-en">T31</span><<span class="pl-c1">number</span>>; <span class="pl-c"><span class="pl-c">//</span> true</span> <span class="pl-k">type</span> <span class="pl-en">b</span> <span class="pl-k">=</span> <span class="pl-en">T31</span><<span class="pl-c1">any</span>>; <span class="pl-c"><span class="pl-c">//</span> true</span></pre></div>spa

<h2>可進行的操做</h2> <p>只能進行等於的判斷,其餘操做則會報錯。</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">function</span> f10(<span class="pl-v">x</span><span class="pl-k">:</span> <span class="pl-c1">unknown</span>) { <span class="pl-smi">x</span> <span class="pl-k">==</span> <span class="pl-c1">5</span>; <span class="pl-smi">x</span> <span class="pl-k">!==</span> <span class="pl-c1">10</span>; <span class="pl-smi">x</span> <span class="pl-k">&gt;=</span> <span class="pl-c1">0</span>; <span class="pl-c"><span class="pl-c">//</span> Error</span> <span class="pl-smi">x</span> <span class="pl-k">+</span> <span class="pl-c1">1</span>; <span class="pl-c"><span class="pl-c">//</span> Error</span> <span class="pl-smi">x</span> <span class="pl-k">*</span> <span class="pl-c1">2</span>; <span class="pl-c"><span class="pl-c">//</span> Error</span> <span class="pl-k">-</span><span class="pl-smi">x</span>; <span class="pl-c"><span class="pl-c">//</span> Error</span> <span class="pl-k">+</span><span class="pl-smi">x</span>; <span class="pl-c"><span class="pl-c">//</span> Error</span> }</pre></div> <p>屬性字段獲取,方法調用等,也是不容許的:</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">function</span> f11(<span class="pl-v">x</span><span class="pl-k">:</span> <span class="pl-c1">unknown</span>) { <span class="pl-smi">x</span>.<span class="pl-smi">foo</span>; <span class="pl-c"><span class="pl-c">//</span> Error</span> <span class="pl-smi">x</span>[<span class="pl-c1">5</span>]; <span class="pl-c"><span class="pl-c">//</span> Error</span> <span class="pl-en">x</span>(); <span class="pl-c"><span class="pl-c">//</span> Error</span> <span class="pl-k">new</span> <span class="pl-en">x</span>(); <span class="pl-c"><span class="pl-c">//</span> Error</span> }</pre></div> <p>當解構中有 <code>unknown</code> 類型時,會致使解構出來的結果也是 <code>unknown</code>。</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">function</span> f26(<span class="pl-v">x</span><span class="pl-k">:</span> {}, <span class="pl-v">y</span><span class="pl-k">:</span> <span class="pl-c1">unknown</span>, <span class="pl-v">z</span><span class="pl-k">:</span> <span class="pl-c1">any</span>) { <span class="pl-k">let</span> o1 <span class="pl-k">=</span> { a: <span class="pl-c1">42</span>, <span class="pl-k">...</span><span class="pl-smi">x</span> }; <span class="pl-c"><span class="pl-c">//</span> { a: number }</span> <span class="pl-k">let</span> o2 <span class="pl-k">=</span> { a: <span class="pl-c1">42</span>, <span class="pl-k">...</span><span class="pl-smi">x</span>, <span class="pl-k">...</span><span class="pl-smi">y</span> }; <span class="pl-c"><span class="pl-c">//</span> unknown</span> <span class="pl-k">let</span> o3 <span class="pl-k">=</span> { a: <span class="pl-c1">42</span>, <span class="pl-k">...</span><span class="pl-smi">x</span>, <span class="pl-k">...</span><span class="pl-smi">y</span>, <span class="pl-k">...</span><span class="pl-smi">z</span> }; <span class="pl-c"><span class="pl-c">//</span> any</span> }</pre></div> <h2>具體使用場景</h2> <p><code>unknown</code> 用於變量類型不肯定,但確定能夠肯定的情形下,好比下面這個示例中,入參總歸會有個值,根據這個值的類型進行不一樣的處理,這裏使用 <code>unknown</code> 替代 <code>any</code> 則會更加類型安全。</p> <div class="highlight highlight-source-ts"><pre><span class="pl-k">function</span> prettyPrint(<span class="pl-v">x</span><span class="pl-k">:</span> <span class="pl-c1">unknown</span>)<span class="pl-k">:</span> <span class="pl-c1">string</span> { <span class="pl-k">if</span> (<span class="pl-c1">Array</span>.<span class="pl-en">isArray</span>(<span class="pl-smi">x</span>)) { <span class="pl-k">return</span> <span class="pl-s"><span class="pl-pds">"</span>[<span class="pl-pds">"</span></span> <span class="pl-k">+</span> <span class="pl-smi">x</span>.<span class="pl-en">map</span>(<span class="pl-smi">prettyPrint</span>).<span class="pl-c1">join</span>(<span class="pl-s"><span class="pl-pds">"</span>, <span class="pl-pds">"</span></span>) <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">"</span>]<span class="pl-pds">"</span></span> } <span class="pl-k">if</span> (<span class="pl-k">typeof</span> <span class="pl-smi">x</span> <span class="pl-k">===</span> <span class="pl-s"><span class="pl-pds">"</span>string<span class="pl-pds">"</span></span>) { <span class="pl-k">return</span> <span class="pl-s"><span class="pl-pds">`</span>"${<span class="pl-smi">x</span>}"<span class="pl-pds">`</span></span> } <span class="pl-k">if</span> (<span class="pl-k">typeof</span> <span class="pl-smi">x</span> <span class="pl-k">===</span> <span class="pl-s"><span class="pl-pds">"</span>number<span class="pl-pds">"</span></span>) { <span class="pl-k">return</span> <span class="pl-c1">String</span>(<span class="pl-smi">x</span>) } <span class="pl-k">return</span> <span class="pl-s"><span class="pl-pds">"</span>etc.<span class="pl-pds">"</span></span> }</pre></div> <h2>相關資源</h2> <ul> <li><a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html" rel="nofollow">TypeScript 3.0 Release notes - New unknown top type</a></li> <li><a href="https://blog.logrocket.com/when-to-use-never-and-unknown-in-typescript-5e4d6c5799ad/" rel="nofollow">When to use <code>never</code> and <code>unknown</code> in TypeScript</a></li> </ul> </td> </tr> </tbody> </table>code

相關文章
相關標籤/搜索