[英]Combine generic interfaces with two generic types into one type with only one generic type
就我而言,我正在使用React的useReducer ,但我的問題是純打字稿問題。
采取以下措施:
export interface State<T> {
values: T;
someOtherProp: boolean;
}
export interface ActionOne<T, K extends keyof T> {
type: "UPDATE_VALUE_ONE";
payload: { name: K; value: T[K] };
}
export interface ActionTwo<T, K extends keyof T> {
type: "UPDATE_VALUE_TWO";
payload: { name: K; value: T[K] };
}
現在,將兩個操作接口合並為一個聯合類型:
type ActionTypes<T, K extends keyof T> = ActionOne<T, K> | ActionTwo<T, K>
在下一步中,函數將使用ActionTypes
作為其參數的類型:
export const reducer = <T>(
state: State<T>,
action: ActionTypes<T> // This already breaks because the second generic type is missing
): State<T> =>
{
switch (action.type) {
case "UPDATE_VALUE_ONE":
return {
...state,
values: { ...state.values, [action.payload.name]: action.payload.value}
};
case "UPDATE_VALUE_ONE":
// ...
}
}
正如您在代碼的注釋中看到的那樣, ActionTypes<T>
已經損壞。 就我而言,我不希望reducer
函數擔心ActionTypes<T, K>
類型K
我知道我可以將keyof T
添加到action: ActionTypes<T, keyof T>
但是這會破壞此行的類型檢查:
values: { ...state.values, [action.payload.name]: action.payload.value}
因為[action.payload.name]
類型可能不同於action.payload.value
實際上,如果ActionType<T, K extends keyof T>
僅具有一個通用類型( T
) ActionType<T, K extends keyof T>
那將是更加理想的選擇。
如果ActionOne
和ActionTwo
是由函數返回的,而不是將它們傳遞為目標,則可以通過內聯聲明這些函數來工作:
type ActionTypes<T> =
| (<T, K extends keyof T>() => ActionOne<T, K>)
| (<T, K extends keyof T>() => ActionTwo<T, K>);`
題
當在僅聲明一個通用類型T
另一個接口/類型中使用接口的第二通用類型K
的信息時,如何“隱藏”該信息? (特別是如果K
仍然是T
的依賴項,則K extends keyof T
)
對於泛型函數,這可以通過內聯聲明解決,那么如何為接口解決呢?
在這種情況下,似乎您希望action
參數是所有可能的動作類型的並集...對於keyof T
每個可能的K
如果是這樣,我將使用分布式條件類型將keyof T
的並集keyof T
分解為每個單獨的文字K
,並獲取所有ActionTypes<T, K>
:
type SomeActionOne<T, K extends keyof T = keyof T> = K extends any
? ActionOne<T, K>
: never;
type SomeActionTwo<T, K extends keyof T = keyof T> = K extends any
? ActionTwo<T, K>
: never;
type AllPossibleActionTypes<T> = SomeActionOne<T> | SomeActionTwo<T>;
(更新:我改性的上述版本AllPossibleActionTypes<T>
到分布在ActionOne<T, K>
對於所有K
,然后分別分配ActionTwo<T, K>
對於所有K
,然后統一它們事后注意,這是。當您指定具體類型T
,它的類型完全相同 ,但是當T
仍是一個無法解析的泛型時,編譯器會對此做出不同的解釋,特別是在舊版本中,編譯器將等待,直到知道T
將類型分為ActionOne
和ActionTwo
品種;現在編譯器從一開始就知道這一點。)
那么reducer
的簽名將是:
export const reducer = <T>(
state: State<T>,
action: AllPossibleActionTypes<T>
): State<T> => { ... }
而且您可以看到在調用reducer()
時得到了合理的提示:
reducer(
{ values: { a: "a", b: 1, c: true }, someOtherProp: true },
{ type: "UPDATE_VALUE_TWO", payload: { name: "b", value: 3 } }
); // hinted for value: number when you type in "b" for name
好的,希望能有所幫助; 祝好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.