TypeScript 將使用 never 類型來表示不應(yīng)該存在的狀態(tài)(很抽象是不是)
// 返回never的函數(shù)必須存在無(wú)法達(dá)到的終點(diǎn)
// 因?yàn)楸囟⊕伋霎惓#?error 將不會(huì)有返回值
function error(message: string): never {
throw new Error(message);
}
// 因?yàn)榇嬖谒姥h(huán),所以 loop 將不會(huì)有返回值
function loop(): never {
while (true) {
}
}
never 與 void 的差異
//void類型只是沒有返回值 但本身不會(huì)出錯(cuò)
function Void():void {
console.log();
}
//只會(huì)拋出異常沒有返回值
function Never():never {
throw new Error('aaa')
}
never 類型的一個(gè)應(yīng)用場(chǎng)景
舉一個(gè)我們可能會(huì)見到的例子
interface A {
type: "foo"
}
interface B {
type: "bar"
}
type All = A | B ;
function handleValue(val: All) {
switch (val.type) {
case 'foo':
break;
case 'bar':
break
default:
//兜底邏輯 一般是不會(huì)進(jìn)入這兒如果進(jìn)來了就是程序異常了
const exhaustiveCheck:never = val;
break
}
}
比如新來了一個(gè)同事他新增了一個(gè)C接口,我們必須手動(dòng)找到所有 switch 代碼并處理,否則將有可能引入 BUG 。
而且這將是一個(gè)“隱蔽型”的BUG,如果回歸面不夠廣,很難發(fā)現(xiàn)此類BUG。
那 TS 有沒有辦法幫助我們?cè)陬愋蜋z查階段發(fā)現(xiàn)這個(gè)問題呢?
interface A {
type: "foo"
}
interface B {
type: "bar"
}
interface C {
type: "bizz"
}
type All = A | B | C;
function handleValue(val: All) {
switch (val.type) {
case 'foo':
break;
case 'bar':
break
default:
//兜底邏輯 一般是不會(huì)進(jìn)入這兒如果進(jìn)來了就是程序異常了
const exhaustiveCheck: never = val;
break
}
}
由于任何類型都不能賦值給 never 類型的變量,所以當(dāng)存在進(jìn)入 default 分支的可能性時(shí),TS的類型檢查會(huì)及時(shí)幫我們發(fā)現(xiàn)這個(gè)問題