GraphQL 查询返回类型的“任何”数据类型

Posted

技术标签:

【中文标题】GraphQL 查询返回类型的“任何”数据类型【英文标题】:"Any" data type for GraphQL Query Return Type 【发布时间】:2020-07-05 05:04:48 【问题描述】:

我对 Typescript 有点陌生,并且在数据类型方面遇到了一些问题。有人告诉我应该避免使用“任何”数据类型,因为它否定了使用 Typescript 的全部意义。但是,我无法更改数据类型。例如,

当我运行 GraphQL 查询时,我使用这个:

   login(
      variables: 
        email: email,
        password: password,
      ,
    )
      .then(( data : any) => 
        localStorage.setItem('token', data.loginEmail.accessToken);
        setShouldRedirect(true);
        //props.history.push("/panel");
      )

data.loginEmail.accessToken 是一个字符串,所以我将 :any 更改为字符串,但出现以下错误:

Argument of type '( data : string) => void' is not assignable to parameter of type '(value: ExecutionResult<any>) => void | PromiseLike<void>'.
  Types of parameters '__0' and 'value' are incompatible.
    Type 'ExecutionResult<any>' is not assignable to type 'string'.  TS2345

如果我将类型更改为object,我会得到Property 'data' does not exist on type ''. TS2339,但文档还说突变返回一个对象。因此,如果不是对象或字符串,我还能如何指定此类对象的数据类型?有可能吗?

同样,当我在查询后映射这样的项目时:

data &&
          data.users.nodes &&
          data.users.nodes.map((c: any, i: any) => (
            <li key=i>
              Id: c.id, First Name: c.firstName, Last Name: c.lastName,
              Email: c.email, phoneNumber: c.phoneNumber
            </li>
          ))

我还能如何指定 c 和 I? i 没有简单的整数选项。

编辑:

架构:

  loginEmail(
    email: String!
    password: String!
  ): SignInResponse!
type SignInResponse 
  accessToken: String!

GraphQL 代码:

export type MutationLoginEmailArgs = 
  email: Scalars['String'],
  password: Scalars['String']
;

【问题讨论】:

试试改成.then(( data : ExecutionResult&lt;data:string;&gt;) =&gt; data : string 没有意义。字符串不是具有.data 属性的对象 @NickSurmanidze 这给了我一个关于data.loginEmail 的错误property loginEmail doesn't exist on type data:string 我也尝试过对象但仍然是同样的问题 是的,你是对的。狂野没用的尝试。 @Bergi 认为由于突变中的两种类型都是字符串,也许有某种方法可以将字符串传递两次?记住这个问题的答案 【参考方案1】:

看起来你的数据结构对应如下类型接口:

interface MyDataReponse 
  users: 
   nodes: 
    id: string; // maybe this is number in your case
    firstName:string;
    lastName: string;
    phoneNumber: string;
    email: string;
   []
  


然后在你的数据上:

.then(( data : ExecutionResult<data:MyDataReponse;>) => 

【讨论】:

它仍然在下一行的 loginEmail 上给出相同的错误。不同之处在于它说MyDataReponse而不是字符串 你知道如何解决这个问题吗?【参考方案2】:

如果你使用 TypeScript,你应该为钩子返回的数据和你传递给它的变量生成类型。可以使用Apollo CLI 或GraphQL Code Generator 来生成类型。

一旦你有了你的类型,你就可以将它们与你的钩子一起使用,如here in the docs所示。通过这样做,您将避免在使用挂钩返回的 data 属性时显式分配类型。您还将为传递给钩子的任何变量添加类型安全性。

文档中的示例用法:

interface RocketInventory 
  id: number;
  model: string;
  year: number;
  stock: number;


interface RocketInventoryData 
  rocketInventory: RocketInventory[];


interface RocketInventoryVars 
  year: number;


const GET_ROCKET_INVENTORY = gql`
  query getRocketInventory($year: Int!) 
    rocketInventory(year: $year) 
      id
      model
      year
      stock
    
  
`;

export const SomeComponent = () => 
  const  loading, data  = useQuery<RocketInventoryData, RocketInventoryVars>(
    GET_ROCKET_INVENTORY,
     variables:  year: 2019  
  );
  ...

【讨论】:

我还是有点迷茫。我尝试了您建议的工具并使用输出编辑了 qs。但是,我仍然不知道如何在我的代码中使用它们。我应该在我的代码中只使用interface LoginEmail email: string; password:string; 吗?但我的问题是我如何才能完全改变data: any 通过将正确的类型传递给 useQuery 钩子,TypeScript 将能够推断 data 的类型,而您可以执行其他任何操作。

以上是关于GraphQL 查询返回类型的“任何”数据类型的主要内容,如果未能解决你的问题,请参考以下文章

对 GraphQL 中嵌套类型的深度查询返回 NULL

介绍 GraphQL

我应该如何确定查询返回到 GraphQL 接口类型的显式类型?

GraphQL 查询工作,现在返回 null;

紧跟在查询类型(query/mutation)GraphQL之后的字符串的意义

GraphQL:返回具有不可为空 id 字段的类型作为查询结果