简体   繁体   English

如何在 React 中为 AWS 放大 GraphQL 响应设置打字稿类型?

[英]How do I set typescript types for an AWS amplify GraphQL response in React?

I have a react component in typescript and I want to set the results of an appsync graphql query to a property in state.我在打字稿中有一个反应组件,我想将 appsync graphql 查询的结果设置为状态属性。

import React, { Component } from 'react';
import { API, graphqlOperation } from 'aws-amplify';
import {ListProjectsQuery} from './API'
import {listProjects } from './graphql/queries';

class App extends Component<{}, {
  projects:ListProjectsQuery
}>  {
  state = {
    projects: null
  };
  async componentDidMount() {
    const projects = await API.graphql(graphqlOperation(listProjects));
    this.setState({ projects });
  }

  ...

How do I define the default state property to make this work?如何定义默认状态属性以使其工作?

I found a similar problem in the amplify github issues but that solution was in the context of a stateless functional component.我在 amplify github 问题中发现了类似的问题,但该解决方案是在无状态功能组件的上下文中。 I am using a stateful component.我正在使用有状态组件。

Depending on what I try I seem to get one of three errors.根据我的尝试,我似乎得到了三个错误之一。

The code above throws Type 'null' is not assignable to type 'ListProjectsQuery'.上面的代码抛出Type 'null' is not assignable to type 'ListProjectsQuery'. . .

This makes sense so I try and map the shape in state like so:这是有道理的,所以我尝试在状态下映射形状,如下所示:

state = {
    projects: {listProjects: {items: [{name: ''}]}}
  }

which makes it throw Types of property 'projects' are incompatible.这使得它抛出Types of property 'projects' are incompatible.

I either get told that a Property does not exist on type 'Observable<object>' or I get told the shape of the default state value is not compatible.我要么被告知Property does not exist on type 'Observable<object>'要么被告知默认状态值的形状不兼容。

Finally I tried to use an interface like in the example I found:最后,我尝试使用我发现的示例中的接口:

interface IListProjectQuery {
  projects: ListProjectsQuery;
}

and then I reference the interface然后我引用了接口

class App extends Component<
  {},
  {
    projects: IListProjectQuery;
  }
> 

and it throws the following error Type '{ projects: null; }' is not assignable to type 'Readonly<{ projects: IListProjectQuery; }>'.并抛出以下错误Type '{ projects: null; }' is not assignable to type 'Readonly<{ projects: IListProjectQuery; }>'. Type '{ projects: null; }' is not assignable to type 'Readonly<{ projects: IListProjectQuery; }>'.

What value do I give the default state property in order for it to make typescript happy?为了让打字稿满意,我应该赋予默认状态属性什么值?

The ListProjectsQuery import is autogenerated by amplify/appsync codegen, the type alias looks like so: ListProjectsQuery导入由 amplify/appsync 代码生成器自动生成,类型别名如下所示:

export type ListProjectsQuery = {
  listProjects:  {
    __typename: "ModelProjectConnection",
    items:  Array< {
      __typename: "Project",
      id: string,
      name: string,
      organisation:  {
        __typename: "Organisation",
        id: string,
        name: string,
      } | null,
      list:  {
        __typename: "ModelListConnection",
        nextToken: string | null,
      } | null,
    } | null > | null,
    nextToken: string | null,
  } | null,
};
  • You have to define a type that matches the structure of data you are expecting from amplify您必须定义一个与您期望的数据结构相匹配的类型 amplify
  • The second step is to cast your response data as the type you defined and that's it.第二步是将您的响应数据转换为您定义的类型,就是这样。
  • Your projects property inside your state should be properly typed, projects: IProject[ ] |您的状态中的项目属性应该正确键入,项目: IProject[ ] | undefined .未定义 You either have an array of projects or it's undefined.您要么有一系列项目,要么未定义。

 export type IProject = { name: string } export type GetProjectsQuery = { listProjects:{ items: IProject[] nextToken: string } } const fetchAllProjects = async () => { try { const result = (await API.graphql(graphqlOperation(queries.listProjects))) as { data: GetProjectsQuery } projects = result.data.listProjects.items } catch (error) { //handle error here }

Make your property optional:使您的财产可选:

class App extends Component<{}, {
  projects?: ListProjectsQuery //<<== note the question mark
}>  {
  state = {
    projects: null
  };
  async componentDidMount() {
    const projects = await API.graphql(graphqlOperation(listProjects));
    this.setState({ projects });
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM