【发布时间】:2019-12-06 03:34:39
【问题描述】:
就我而言,我正在使用来自 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) 会更理想。
如果 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 由K extends keyof T。)
对于泛型函数,这可以通过内联声明来解决,那么对于接口如何解决呢?
【问题讨论】:
-
type ActionTypes
= IActionOne | IActionTwo ; -
正如我在帖子中已经说过的,这不会有帮助,因为它会破坏类型检查..
标签: reactjs typescript generics typescript-generics