【问题标题】:How to handle repeated similar types in TypeScript如何在 TypeScript 中处理重复的相似类型
【发布时间】:2021-11-27 02:09:48
【问题描述】:

在我的应用程序的简化版本中,我从服务器接收 cmets,每个评论都将回复数组作为属性。我想规范我的状态,以便我将没有回复的 cmets 作为状态的一部分,并将回复作为状态的第二部分。

当我创建评论时,我只提交 authorbody。当我收到来自服务器的评论时,我会得到其他属性以及 replies 数组,并且处于我希望 cmets 没有回复的状态。

因为如果在我的types.ts 文件中,我有 4 个不同的接口。一个是新评论,另一个是进入状态的没有回复的评论,第三个是从服务器收到的整个评论,第四个是回复。

export interface NewComment {
  author: string,
  body: string
}

export interface CommentWithoutReplies {
  id: string,
  author: string,
  body: string,
  postedAt: number,
  replies_count: number,
}

export interface Comment {
  id: string,
  author: string,
  body: string,
  postedAt: number,
  replies_count: number,
  replies: Reply[]
}

export interface Reply {
  id: string
  comment_id: string,
  author: string,
  body: string,
  postedAt: number,
}

我正在使用创建一个现在看起来像这样并通过检查的评论上下文文件:

import { createContext, useCallback, useState, FC } from "react";
import {Comment, CommentWithoutReplies, CommentContextState, CommentContextDispatch} from "../types/types"

const defaultStateValue: CommentContextState = {
  comments: [],
};
const defaultDispatchValue: CommentContextDispatch = {
  getComments: () => undefined,
  addComment: () => undefined,
};

export const CommentStateContext = createContext<CommentContextState>(defaultStateValue);
export const CommentDispatchContext = createContext<CommentContextDispatch>(defaultDispatchValue);

const CommentProvider: FC = ({children}) => {
  const [comments, setComments] = useState<CommentWithoutReplies[]>(defaultStateValue.comments);

  const getComments = useCallback(
    (data: Comment[]) => {
      setComments(() => {
        return data.map(comment => {
          const {replies, ...commentWithoutReplies} = comment;
          return commentWithoutReplies
        })
      });
    },
    [setComments]
  );

  const addComment = useCallback(
    (data: CommentWithoutReplies) => {
      setComments((currentComments: CommentWithoutReplies[]) => {
        return [...currentComments, data];
      });
    },
    [setComments]
  );

  return (
    <CommentDispatchContext.Provider
      value={{
        getComments,
        addComment,
      }}
    >
      <CommentStateContext.Provider
        value={{
          comments,
        }}
      >
        {children}
      </CommentStateContext.Provider>
    </CommentDispatchContext.Provider>
  );
};

export default CommentProvider;

有没有比拥有 4 个不同的接口更优雅的方式来处理这些类型?

【问题讨论】:

    标签: reactjs typescript types context-api


    【解决方案1】:

    在我看来,您现在所做的事情非常合理 - 您正在使用多个单独的数据形状,因此在大多数情况下,您需要在某个地方定义这些形状中的每一个。不过,您可以通过在不必要时不注意类型来减少重复性,例如这个

    setComments((currentComments: CommentWithoutReplies[]) => {
    

    可以

    setComments((currentComments) => {
    

    您可以从包含所有共同属性的基本类型开始更简洁地定义类型 - idauthorpostedAt

    type BaseComment {
        id: string,
        author: string,
        postedAt: number,
    }
    export type CommentWithoutReplies = BaseComment & {
        body: string,
        replies_count: number,
    }
    export type Comment = BaseComment & {
        body: string,
        replies_count: number,
        replies: Reply[]
    }
    export type Reply = BaseComment & {
        comment_id: string,
        body: string,
    }
    

    不知道你还有什么其他代码,但如果这里的类型没有在其他地方导入,你也可以在上下文文件本身中定义它们,而不必导入它们。

    【讨论】:

      猜你喜欢
      • 2021-01-26
      • 2018-03-12
      • 1970-01-01
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      相关资源
      最近更新 更多