将响应列表转换为混合型列表



我从API调用中获得一个项目列表,其结构如下:

interface Event {
id: string
type: EventType_Enum
timestamp: Date
payload: string
}

根据类型,事件在payload变量中具有不同结构的JSON字符串。对于保存响应,这个接口就足够了,但是对于根据这些事件处理UI,将这个Event[]转换为每种类型的事件混合列表会更好。因此,每个类型都应该有自己的接口,该接口不再具有payload变量,而是具有完全类型的字段。例如

interface EventType1 {
id: string
timestamp: Date
typeField1: number
typeField2: string
// ... etc
}

这样我将得到一个包含多种类型元素的列表。

我的问题:

  1. 如何在打字稿中完成从payload列表到混合列表的转换?
  2. UI如何在事件类型上有条件地呈现从这个结果混合列表?是否可以在typescript中添加自定义方法到接口(例如render),然后在混合列表中为每个条目调用此方法?

我对Typescript的理解有限,所以请把它看作一个伪代码,这里是一个粗略的想法。

请考虑权衡,对于少数事件类型这是一个过度,但如果许多事件类型预期,那么这似乎是正确的方向。请提供你的评论来改进这一点。

  • 将有效负载从字符串转换为对象,如果JSON.parse()不起作用如预期的那样,创建函数来处理每个事件类型负载和创建一个字典来选择正确的函数。

  • 的优点是,如果有太多的事件添加新的将不破坏现有代码。

    处理需要在渲染之前完成,所以渲染Items不需要再做一次

    // outside the component if possible
    const poorMansTransformerFactory = {
    [EventType_Enum.event1]: transformerForEvent1,
    [EventType_Enum.event2]: transformerForEvent2,
    }
    // in component
    const [eventList, setEventList] = useState([])
    // setEventList in fetch in some parent component
    // either transform in the fetch function
    // if you dont have access to fetch, then useMemo
    const transformedEvents = useMemo(() => {
    // add try catch and extra checks
    const transformedEvents = eventList.map(eventItem => {
    const { type, v } = eventItem;
    const transformerFunction = poorMansTransformerFactory[type] ?? defaultTransformerFunction;
    return {
    ...eventItem,
    payload: transformerFunction(payload)
    }
    }) 
    }, [eventList])
    
    interface Payload {
    [prop: string]: any;
    }
    interface Event {
    id: string
    type: EventType_Enum
    timestamp: Date
    payload: Payload // needs someting better
    }
    

如果你可以为每种类型创建一个组件字典,这样你就不必担心一个事件类型的任何更改会影响其他事件

const EventOneComponent = ({ props }) => { // event specific props
return ( // view for specific event
}
const poorMansFactory = {
[EventType_Enum.event1]: EventOneComponent,
[EventType_Enum.event2]: EventTwoComponent,
}
// usage
// will select the right component to render the event type
const EventItem = (props) => {

const { type, payload } = props;
const EventRenderer = useMemo(() => {
return poorMansFactory[type] ?? DefaultEventRenderer;
}, [type])

return (
... common render components
<EventRenderer {...payload} /> // pass props as needed
)
}

// rendering EventItem in some list 
transformedEvents.map(event => {
return (<EventItem key={event.id} {...event } />)
}

希望它能有所帮助,我很好奇它是如何工作的

最新更新