[英]Can nested switch statements be exhaustive in TypeScript?
看起來以下代碼沒有在TypeScript中鍵入check。
interface A {
type: 'a',
number: Number
}
interface B {
type: 'b',
number: Number
}
type Letter = A | B
interface One {
type: 'one'
}
interface Two {
type: 'two'
}
type Number = One | Two;
function we(letter: Letter): boolean { // claims boolean isn't always returned
switch (letter.type) {
case 'a':
return true;
case 'b':
const number = letter.number;
switch (number.type) {
case 'one':
return true;
case 'two':
return true;
}
}
}
我可以在內部開關中添加默認值以使其正常工作,但令我驚訝的是我需要一個平面開關就可以了。 這到底是怎么回事?
這里的問題是您尚未處理數據不是您聲明的那樣的情況。 也許某個地方可以強制轉換為任何一個,然后分配letter.type='c'
。 或就此而言,就這樣稱呼它:
we({type: 'c'} as any as Letter);
雙重強制轉換確保您不會收到編譯器警告,但這不是您在函數中允許的情況。
這是一種排序方式:
function exhaustiveCheck(value: never): never {
throw(new Error('switch was not exhaustive'));
}
function we(letter: Letter): boolean {
switch (letter.type) {
case 'a':
return true;
case 'b':
const number = letter.number;
switch (number.type) {
case 'one':
return true;
// case 'two':
// return true;
default:
return exhaustiveCheck(number);
}
default: {
return exhaustiveCheck(letter);
}
}
}
這樣可以確保在運行時,如果您獲得的數據不是所描述的類型系統,則將對其進行檢查並引發錯誤,但在編譯時,還可以確保您已徹底處理所有情況。
在我編寫上面的代碼時,您收到對exhaustiveCheck(number)
的調用的編譯時錯誤,取消注釋其上方的兩行,該錯誤將消失。 由於在默認情況下我們已經覆蓋了A
和B
類型,因此第二次調用了exhaustiveCheck(letter)
,因此剩下的唯一情況是letter
的類型為never
:這意味着就類型系統而言即使在運行時也有可能發生,但絕不應該發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.