您如何建议合并具有相同属性但值类型不同的接口
Posted
技术标签:
【中文标题】您如何建议合并具有相同属性但值类型不同的接口【英文标题】:How would you suggest to merge interfaces with same properties but different value types 【发布时间】:2021-11-08 23:38:46 【问题描述】:我在 ReactJS 上使用 useReducer
,并且我定义了几个操作接口以在我的 reducer function
中使用它们。我看到我使用相同的属性,但有时不同的有效负载值。
interface MembersAction
type: "JOIN" | "LEAVE";
payload: string;
interface MessagesAction
type: "MESSAGE";
payload: Message;
interface ErrorAction
type: "ERROR";
payload: string;
interface RoomAction
type: "ROOM";
payload: RoomData;
说实话,感觉有点臃肿,我觉得必须有更好的方法来实现我正在做的事情。
reducer 函数如下:
type Action = MembersAction | MessagesAction | RoomAction | ErrorAction;
const reducer = (state: RoomState, action: Action) =>
switch (action.type)
case "JOIN":
return
...state,
members: [...state.members, action.payload],
;
case "LEAVE":
return
...state,
members: state.members.splice(state.members.indexOf(action.payload), 1),
;
case "MESSAGE":
return
...state,
messages: [...state.messages, action.payload],
;
case "ROOM":
return action.payload;
case "ERROR":
return state.error
?
...state,
:
...state,
error: action.payload,
;
default:
return state;
;
【问题讨论】:
不幸的是,我认为没有更好的方法可以做到这一点。此人有一个similar question,答案类似于您的解决方案。不过,您可以通过组合 Members 和 Error 操作来稍微缩短代码。 【参考方案1】:您的代码在我看来很好,并且在 playground link 中表现良好。
您已将其正确表达为 discriminated union,这样 TypeScript 就可以在switch
块中正确推断您的 payload
类型。
您的 payload
类型在您的不同操作之间不兼容,因此通过多态处理 payload
在这里没有什么好处。
您的 reducer 近似于 visitor pattern,尽管 Typescript 的结构类型意味着您避免了一些通常与该模式相关的接口。如果你的 reducer 表达的操作本质上是一个 Action 应该能够对自己做的事情,我可以看到重构的价值,所以每个 Action 都提供了一个方法的实现,就像你的 reducer
可以,但它接受一些类定义样板而不是你的 switch
语句样板。
在考虑这一点时,请确定您是否更有可能添加需要表达新行为的操作(例如,应将行为封装在操作中),或者添加操作的自包含函数大多数或所有新操作(这样行为应该像您一样封装在switch
中)。如果不清楚,请留下 - 就我个人而言,我很乐意接受您拥有的定义明确的代码。
【讨论】:
以上是关于您如何建议合并具有相同属性但值类型不同的接口的主要内容,如果未能解决你的问题,请参考以下文章
如何创建具有索引签名和不同类型的固定属性的 TypeScript 接口?