[英]Dynamic dispatch of discriminated unions
我正在嘗試編寫一個經過完全類型檢查的有區別的聯合類型的動態調度程序。 我覺得我已經很接近了,但是我不知道如何獲得正確鍵入check的最后一步。
interface A {
kind: 'a'
}
interface B {
kind: 'b'
}
type Union = A | B
function aHandler(a: A) {}
function bHandler(b: B) {}
const mapping: { [TKind in Union['kind']]: (param: Extract<Union, { kind: TKind }>) => void } = {
a: aHandler,
b: bHandler,
}
const aInstance: A = { kind: 'a' }
const bInstance: B = { kind: 'b' }
var unionInstance: Union = ((): Union => {throw ''})()
mapping[aInstance.kind](aInstance) // no error
mapping[aInstance.kind](bInstance) // errors correctly
mapping[unionInstance.kind](unionInstance) // errors unexpectedly
如代碼片段所示,問題出在最后一行。 類型系統知道每個TKind都有一個映射到封裝該特定TKind的類型的處理程序的映射,我們可以在最后一行的上方兩行看到它正確處理了這種情況。
我認為問題在於,在執行映射查找時,類型檢查器沒有在最后一行中縮小unionInstance
,因此它會將對mapping[TKind](...)
的參數視為Union而不是縮小的A或B 。
我們可以看到這種通用模式應該起作用,因為我們可以創建一個單獨處理每種情況的switch語句。 緊接着,我相信這是起作用的原因。
switch (unionInstance.kind) {
case 'a': mapping[unionInstance.kind](unionInstance); break
case 'b': mapping[unionInstance.kind](unionInstance); break
default: assertNever(unionInstance)
}
有什么我可以解決的方法,以便我可以編寫帶有嚴格類型檢查的有區別的聯合調度程序?
目前尚無法實現。 Typescript不會跟蹤索引訪問和傳入的參數相關的事實。
有一個提議允許這樣做,但沒有透露何時會發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.