我有一个客户端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
对象,但仅具有2个字段:firstName
和secondName
。在这种情况下,我应该创建另一个接口吗?喜欢:
interface AuthorFullname {
firstName: string;
lastName: string;
}
或者我可以只将属于IUser
GQL类型的任何内容强制转换为Author
吗?然后在代码中,我会小心,因为我知道user
对象只包含firstName
和lastName
。因此,我将不使用firstName
和lastName
以外的其他字段。
答案 0 :(得分:1)
如果可以生成代码,可以在客户端应用程序上使用名为apollo codegen的工具。
基本上,它检查定义查询gql
的每个位置,并与服务器schema
定义一起为定义的查询生成必要的Interfaces
。因此,如果您定义嵌套查询或带有片段的查询,它将仅生成执行它们所需的接口。
这也是一篇有关Generate TypeScript Definitions for GraphQL Queries的好文章。
答案 1 :(得分:0)
这是一个很大的问题,因为GraphQL接口可能会返回该接口的部分版本,所以最好使用Partial这样的Typescript HOC类型
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 :(得分:0)
一种方法是简单地创建特定于您在代码中实际使用的每个查询的接口。例如,给定两个查询:
query QueryA {
allAuthors {
id
firstName
lastName
posts {
...PostFields
}
}
}
query QueryB {
id
firstName
lastName
}
我们可以只创建两个单独的接口,每个查询一个:
interface QueryAAuthor {
id: number;
firstName: string;
lastName: string;
posts: QuaryAPost[];
}
interface QueryBAuthor {
id: number;
firstName: string;
lastName: string;
}
尽管这确实会创建更多接口并在代码中产生额外的复杂性,但这也意味着在处理查询结果时没有歧义。例如,如果我们改为将单个接口与Partial
一起使用,即使处理QueryB的结果并且编译器也无法捕获它,我仍然可以引用posts
。
这实际上是Apollo CLI的代码生成功能所使用的方法,它使您可以基于模式和客户端查询生成类型。
我认为这不是处理它的唯一方法-只是您的代码中想要多少类型安全性的问题。