【问题标题】:Lifting nested object properties one level in TypeScript在 TypeScript 中将嵌套对象属性提升一级
【发布时间】:2021-08-29 21:48:49
【问题描述】:

我目前正在处理一个项目,其中包含来自 GraphQL API 的一些大型对象。我正在使用 TypeScript,在设置 Apollo 客户端为所有 GraphQL 查询生成类型注释之后,处理数据要容易得多。但是,我遇到了一个不确定如何在 TypeScript 中处理的问题。

因为我只对我需要的数据进行查询(这就是 GraphQL 的重点),所以我经常有具有“额外”不必要级别的对象结构。在 Javascript 中,我只会将对象属性提升一级,但在 TypeScript 中,我需要一些最佳实践方面的帮助???

一个简单的例子:

if (data?.featuredImage) {
    data.featuredImage = data?.featuredImage?.node;
  }

与往常一样,您几乎可以摆脱 Javascript 中的所有内容,但是 TypeScript 中的任何提示? 我需要以某种方式清理数据 - 否则代码将太难以维护......

所有类型都是自动生成的,但我当然可以扩展类型/接口并手动创建额外的类型。

Here is a minimal example at TS Playground

【问题讨论】:

  • 如果您的代码是 minimal reproducible example 适合在像 The TypeScript Playground (link to code) 这样的独立 IDE 中演示该问题,那就太好了,这样想要帮助的人就可以开始工作了回答而不是花时间重现问题中的问题。
  • 酷 jcalz 我以前没见过 TyeScript 操场。我将编辑帖子并举例说明并重新发布。谢谢!
  • 坏例子至少有两个原因:1.不同/不匹配的数据类型,2.[通常]只读data道具的突变(不仅仅是TS问题)......定义一些新的节点类型的常量
  • 嗨 xadm。在其他人清理 GraphQL 数据时,我实际上已经看到过这种模式。这就是 TypeScript 的问题:你开始认为仅仅因为它可以完成它并不一定是一个好主意。只是要明确一点:您将如何做到这一点?这对我来说并不明显。 “数据”对象非常大,我可能需要对对象的不同属性以及一些映射执行 10 次类似的操作。
  • 只需创建一个别名/快捷方式,如if(!data) return <Loading />; const featuredImage = data?.featuredImage?.node; return <Post image={featuredImage} />;

标签: typescript object graphql apollo-client


【解决方案1】:

好吧,因为我需要将我的对象的某些部分与另一个对象进行比较,并且还需要进行一些映射,所以我仍然需要一种提升对象属性的方法。我找到了一个可行的解决方案。我不确定这是否是 hacky,但现在它完成了工作:

通过使用扩展运算符和一个单独的对象 (originalData),我可以获得所有属性并覆盖我需要提升一个级别的属性,而 TypeScript 不会引发错误。示例:

const originalData = { ...page };
  let featuredImage: PageByUri_page_featuredImage_node | null = null;
  let parent: PageByUri_page_parent_node | null = null;
  let children: (PageByUri_page_children_edges_node | null| undefined)[] = [null];

  if (!!originalData?.featuredImage?.node) {
    featuredImage = originalData?.featuredImage?.node;
  } 

  if (!!originalData?.parent?.node) {
    parent = originalData.parent.node;
  } 

  if (!!originalData?.children?.edges) {
    children = originalData.children.edges?.map((node) => node?.node);
  }

  const data = {...originalData, featuredImage, parent, children }
  
  return data;

如果属性为 null,它们将保持为 null,如果它们存在于对象树中,属性将被覆盖。如果有人有更好的方法来清理复杂的 graphQL 对象,我很想知道!

【讨论】:

  • featuredImage = originalData?.featuredImage?.node || null; - 不需要if 包装? ...但仍将其视为人工(或其他地方/结构)问题(道具钻孔?可能的分页道具丢失 - 如果需要分页支持,则进行更多不必要的更改?) ... onCompleted+local state 或 useMemo/@ 987654326@ 用于转化
  • 是的!我显然需要重新考虑一些东西并进行一些重构!我发现使用 TypeScript 最困难的是我需要重新考虑很多代码,以及我通常是如何做事的!
猜你喜欢
  • 1970-01-01
  • 2018-06-29
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多