客户端 Typescript 应用程序和 GraphQL 后端的一般工作流程是啥

Posted

技术标签:

【中文标题】客户端 Typescript 应用程序和 GraphQL 后端的一般工作流程是啥【英文标题】:What is general workflow with client side Typescript app and GraphQL backend客户端 Typescript 应用程序和 GraphQL 后端的一般工作流程是什么 【发布时间】:2019-08-24 20:29:20 【问题描述】:

我有一个客户端 React Typescript 应用程序。我读到为来自端点的响应创建接口是一种很好的做法。

例如 GraphQL 架构声明了这种类型:

type Author 
  id: Int!
  firstName: String!
  lastName: String!
  ... more fields
  posts(findTitle: String): [Post]

所以在客户端我也需要创建类似的界面:

interface Post: ...

interface IAuthor 
  id: number;
  firstName: string;
  lastName: string;
  posts: Post[]

当客户端应用程序收到响应时,它只会将响应投射到该接口,如下所示:

const data = await getWholeAuthorFromGraphQL();
const user = data as IUser;

但我不清楚的一件事是 GraphQL 允许获取特定字段而不是整个对象。

例如,在其他应用程序中,我还需要IUser 对象,但只有两个字段:firstNamesecondName。在这种情况下我应该创建另一个接口吗?喜欢:

interface AuthorFullname 
  firstName: string;
  lastName: string;

或者我可以将属于Author GQL 类型的任何内容转换为IUser 吗?然后在代码中我会小心,因为我会知道user 对象只包含firstNamelastName。所以我不会使用firstNamelastName以外的其他字段。

【问题讨论】:

【参考方案1】:

这是一个很好的问题,鉴于 GraphQL 接口可能会返回接口的部分版本,您最好使用 Typescript HOC 类型,例如 Partial

const getResult : Partial<MyModel> = await yourNetworkRequest()

在这种情况下,Partial 将使每个属性都是可选的,这意味着您可以在实际调用站点进行存在性检查以获取响应。如果您将 Typescript 设置为严格模式,这将特别有用。

您也可以打电话

function myNetworkCall() : Partial<MyModel>

这再次应用相同的事情,然后您必须做繁重的工作以确保您正在寻找的字段存在(通过存在检查)

// assume the following
interface MyModel 
 field1: string;
 field2: string;





const item = myNetworkCall()
if(item.field1)
 // etc

【讨论】:

【参考方案2】:

如果您对生成的代码感到满意,则可以在您的客户端应用程序上使用名为 apollo codegen 的工具。

基本上,它会检查您定义查询gql 的每个位置,并与服务器schema 定义一起为定义的查询生成必要的Interfaces。因此,如果您定义嵌套查询或带有片段的查询,它只会生成执行它们所需的接口。

这里还有一篇关于Generate TypeScript Definitions for GraphQL Queries的好文章。

【讨论】:

【参考方案3】:

一种方法是简单地创建特定于您在代码中实际使用的每个查询的接口。例如,给定两个查询:

query QueryA 
  allAuthors 
    id
    firstName
    lastName
    posts 
      ...PostFields
    
  


query QueryB 
  id
  firstName
  lastName

我们可以只创建两个独立的接口,每个查询一个:

interface QueryAAuthor 
  id: number;
  firstName: string;
  lastName: string;
  posts: QueryAPost[];


interface QueryBAuthor 
  id: number;
  firstName: string;
  lastName: string;

虽然这确实会在您的代码中创建更多接口并产生额外的复杂性,但这也意味着您在处理查询结果时不会有歧义。例如,如果我们要使用 Partial 的单个接口,即使在处理 QueryB 的结果时,我仍然可以引用 posts 并且编译器不会捕获它。

这实际上是 Apollo CLI 的代码生成功能使用的方法,它允许您根据架构和客户端查询生成类型。

我不认为这是处理它的唯一方法——这只是你希望代码中的类型安全程度的问题。

【讨论】:

以上是关于客户端 Typescript 应用程序和 GraphQL 后端的一般工作流程是啥的主要内容,如果未能解决你的问题,请参考以下文章

常见排序算法-----希尔排序

如何使用 GraphQL 构建 TypeScript+React 应用

React Graphql Typescript 文件设置

单个 JavaScript 文件的 TypeScript 定义

带角度的C++ HTTP服务器(客户端的Typescript)[关闭]

在 Angular2 中使用生成的 Swagger TypeScript Rest Client