TypeScript之a(chǎn)ny類型,unknown類型,never類型使用詳解
TypeScript 的三種特殊類型,分別為:any,unknown, never
any 類型
基本含義
any 類型表示沒有任何限制,該類型的變量可以賦予任意類型的值。
let name:any = "hiyooo" name.first = "輕奢男裝店" //不報(bào)錯(cuò) name.address = ['店鋪正在開啟中,有意,可以添加微信:Hi_YOOO'] name() //不報(bào)錯(cuò) ,
變量類型一旦設(shè)為any,TypeScript 實(shí)際上會(huì)關(guān)閉這個(gè)變量的類型檢查。即使有明顯的類型錯(cuò)誤,只要句法正確,都不會(huì)報(bào)錯(cuò)。
由于這個(gè)原因,應(yīng)該盡量避免使用any類型,否則就失去了使用 TypeScript 的意義。
*注,但也不是說,就不能使用any 來聲明變量的類型
實(shí)際開發(fā)中,any類型主要適用以下兩個(gè)場(chǎng)合。
(1)出于特殊原因,需要關(guān)閉某些變量的類型檢查,就可以把該變量的類型設(shè)為any。
(2)為了適配以前老的 JavaScript 項(xiàng)目,讓代碼快速遷移到 TypeScript,可以把變量類型設(shè)為any。有些年代很久的大型 JavaScript 項(xiàng)目,尤其是別人的代碼,很難為每一行適配正確的類型,這時(shí)你為那些類型復(fù)雜的變量加上any,TypeScript 編譯時(shí)就不會(huì)報(bào)錯(cuò)。
總之,TypeScript 認(rèn)為,只要開發(fā)者使用了any類型,就表示開發(fā)者想要自己來處理這些代碼,所以就不對(duì)any類型進(jìn)行任何限制,怎么使用都可以。
從集合論的角度看,any類型可以看成是所有其他類型的全集,包含了一切可能的類型。TypeScript 將這種類型稱為“頂層類型”(top type),意為涵蓋了所有下層。
類型推斷問題
對(duì)于開發(fā)者沒有指定類型、TypeScript 必須自己推斷類型的那些變量,如果無法推斷出類型,TypeScript 就會(huì)認(rèn)為該變量的類型是any。
function add(x, y) {
return x + y;
}
add(1, [1, 2, 3]); // 不報(bào)錯(cuò)上面示例中,函數(shù)add()的參數(shù)變量x和y,都沒有足夠的信息,TypeScript 無法推斷出它們的類型,就會(huì)認(rèn)為這兩個(gè)變量和函數(shù)返回值的類型都是any。以至于后面就不再對(duì)函數(shù)add()進(jìn)行類型檢查了,怎么用都可以。
這顯然是很糟糕的情況,所以對(duì)于那些類型不明顯的變量,一定要顯式聲明類型,防止被推斷為any。
TypeScript 提供了一個(gè)編譯選項(xiàng)noImplicitAny,打開該選項(xiàng),只要推斷出any類型就會(huì)報(bào)錯(cuò)。
此時(shí)可以在tsconfig.json中配置 :noImplicitAny

上面命令使用了noImplicitAny編譯選項(xiàng)進(jìn)行編譯,這時(shí)上面的函數(shù)add()就會(huì)報(bào)錯(cuò)。
污染問題
any類型除了關(guān)閉類型檢查,還有一個(gè)很大的問題,就是它會(huì)“污染”其他變量。它可以賦值給其他任何類型的變量(因?yàn)闆]有類型檢查),導(dǎo)致其他變量出錯(cuò)。
let x :any = "aa"
let y :number =10;
y = x; //不會(huì)報(bào)錯(cuò)
y += 10; //不會(huì)報(bào)錯(cuò)
y.toFixed(1) //不會(huì)報(bào)錯(cuò)上面示例中,變量x的類型是any,實(shí)際的值是一個(gè)字符串。變量y的類型是number,表示這是一個(gè)數(shù)值變量,但是它被賦值為x,這時(shí)并不會(huì)報(bào)錯(cuò)。然后,變量y繼續(xù)進(jìn)行各種數(shù)值運(yùn)算,TypeScript 也檢查不出錯(cuò)誤,問題就這樣留到運(yùn)行時(shí)才會(huì)暴露。
污染其他具有正確類型的變量,把錯(cuò)誤留到運(yùn)行時(shí),這就是不宜使用any類型的另一個(gè)主要原因。
unkown 類型
基本含義
它與any含義相同,表示類型不確定,可能是任意類型。
為了解決any類型“污染”其他變量的問題,TypeScript 3.0 引入了unknown類型,它與any含義相同,表示類型不確定,可能是任意類型,但是它的使用有一些限制,不像any那樣自由,可以視為嚴(yán)格版的any。
unknown跟any的相似之處,在于所有類型的值都可以分配給unknown類型。
let name: unknown; name = true; // 正確 name = 42; // 正確 name = "hiyooo"; // 正確
上面示例中,變量x的類型是unknown,可以賦值為各種類型的值。這與any的行為一致。
unknown類型跟any類型的不同之處在于,它不能直接使用。主要有以下幾個(gè)限制。
1).unknown類型的變量,不能直接賦值給其他類型的變量(除了any類型和unknown類型)。
2).不能直接調(diào)用unknown類型變量的方法和屬性。
3).unknown類型變量能夠進(jìn)行的運(yùn)算是有限的,只能進(jìn)行比較運(yùn)算(運(yùn)算符==、===、!=、!==、||、&&、?)、取反運(yùn)算(運(yùn)算符!)、typeof運(yùn)算符和instanceof運(yùn)算符這幾種,其他運(yùn)算都會(huì)報(bào)錯(cuò)。
1).
let name:unknown;
let first_name:string = name;// error 不能將類型“unknown”分配給類型“string”
let age:number = name; // error 不能將類型“unknown”分配給類型“number”
// 這就避免了污染問題,從而克服了any類型的一大缺點(diǎn)。
2).
let persion:unknown = {name:"hiyooo"}
persion.name;//error 這里會(huì)報(bào)錯(cuò)。 “person”的類型為“未知”
3).
let hiyooo: unknown = 1;
hiyooo + 1; // 報(bào)錯(cuò) “hiyooo”的類型為“未知”。
hiyooo === 1; // 正確那么,怎么才能使用unknown類型變量呢?
答案是只有經(jīng)過“類型縮小”,unknown類型變量才可以使用。所謂“類型縮小”,就是縮小unknown變量的類型范圍,確保不會(huì)出錯(cuò)。
let hiyooo: unknown = 1;
if (typeof hiyooo === "number") {
let r = hiyooo + 10; // 正確
}這樣設(shè)計(jì)的目的是,只有明確unknown變量的實(shí)際類型,才允許使用它,防止像any那樣可以隨意亂用,“污染”其他變量。類型縮小以后再使用,就不會(huì)報(bào)錯(cuò)。
總之,unknown可以看作是更安全的any。一般來說,凡是需要設(shè)為any類型的地方,通常都應(yīng)該優(yōu)先考慮設(shè)為unknown類型。
在集合論上,unknown也可以視為所有其他類型(除了any)的全集,所以它和any一樣,也屬于 TypeScript 的頂層類型。
never 類型
基本含義
類型為空,不包含任何值。
目的
為了保持與集合論的對(duì)應(yīng)關(guān)系,以及類型運(yùn)算的完整性,TypeScript 還引入了“空類型”的概念,即該類型為空,不包含任何值。
由于不存在任何屬于“空類型”的值,所以該類型被稱為never,即不可能有這樣的值。
let hiyooo:never;
,變量hiyooo的類型是never,就不可能賦給它任何值,否則都會(huì)報(bào)錯(cuò)。

never類型的使用場(chǎng)景,主要是在一些類型運(yùn)算之中,保證類型運(yùn)算的完整性
如果一個(gè)變量可能有多種類型(即聯(lián)合類型),通常需要使用分支處理每一種類型。這時(shí),處理所有可能的類型之后,剩余的情況就屬于never類型。
function fn(x: string | number) {
if (typeof x === "string") {
// ...
} else if (typeof x === "number") {
// ...
} else {
x; // never 類型
}
}never類型的一個(gè)重要特點(diǎn)是,可以賦值給任意其他類型。
function f(): never {
throw new Error("Error");
}
let v1: number = f(); // 不報(bào)錯(cuò)
let v2: string = f(); // 不報(bào)錯(cuò)
let v3: boolean = f(); // 不報(bào)錯(cuò)總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
微信小程序?qū)崿F(xiàn)MUI數(shù)字輸入框效果
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)MUI數(shù)字輸入框效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
layui 對(duì)彈窗 form表單賦值的實(shí)現(xiàn)方法
今天小編就為大家分享一篇layui 對(duì)彈窗 form表單賦值的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09
uniapp電商小程序?qū)崿F(xiàn)訂單30分鐘倒計(jì)時(shí)
這篇文章主要為大家詳細(xì)介紹了uniapp電商小程序?qū)崿F(xiàn)訂單30分鐘倒計(jì)時(shí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
js canvas實(shí)現(xiàn)寫字動(dòng)畫效果
這篇文章主要為大家詳細(xì)介紹了js canvas實(shí)現(xiàn)寫字動(dòng)畫效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
使用JavaScript獲取Django模板指定鍵值數(shù)據(jù)
這篇文章主要介紹了使用JavaScript獲取Django模板指定鍵值數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05

