就我而言,我正在使用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
函数担心K
的{{1}}是什么类型。
我知道我可以将ActionTypes<T, 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
和ActionOne
是由函数返回的,而不是像目标那样直接传递它们,它将通过内联声明这些函数来工作:
ActionTwo
问题
当在仅声明一个通用类型type ActionTypes<T> =
| (<T, K extends keyof T>() => ActionOne<T, K>)
| (<T, K extends keyof T>() => ActionTwo<T, K>);`
的另一个接口/类型中使用接口的第二通用类型K
的信息时,如何“隐藏”该信息? (特别是如果T
始终由K
依赖于T
。)
对于泛型函数,这可以通过内联声明解决,那么如何为接口解决呢?
答案 0 :(得分:0)
在这种情况下,似乎您希望action
参数是所有可能的操作类型的并集...对于K
中的每个可能的keyof T
。如果是这样,我将使用distributive conditional type将联合keyof T
分解为每个单独的文字K
,并获得所有ActionTypes<T, K>
的联合:
type AllPossibleActionTypes<T, K extends keyof T = keyof T> = K extends any
? ActionTypes<T, K>
: never;
然后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
好的,希望能有所帮助;祝你好运!