React Apollo中GraphQL查询的TypeScript接口如何正确编写?
Let's fix those TypeScript errors by correcting your interface definitions and aligning them with how react-apollo's Query component passes data to its render prop.
What's causing the errors?
The two issues stem from a mismatch between your custom SectionTableQueryProps interface and the actual data shape the Query component provides:
- Your interface incorrectly places
allTeamsat the top level, but theQuerycomponent wraps all fetched data inside adataobject. - The interface doesn't include the required
dataproperty, which triggers the "Property 'data' does not exist on type 'SectionTableQueryProps'" error.
Solution 1: Use react-apollo's built-in QueryResult type (Recommended)
Instead of building an interface from scratch, use the QueryResult generic type provided by react-apollo. It already includes all the properties the Query component passes (data, error, loading, etc.), and you just need to pass your custom Data interface to type the fetched data correctly.
First, update your imports to include QueryResult:
import { Query, QueryResult } from 'react-apollo';
Then, replace your incorrect SectionTableQueryProps with this typed QueryResult and adjust the component code:
import React from 'react'; import gql from 'graphql-tag'; import { Query, QueryResult } from 'react-apollo'; import { ApolloError } from 'apollo-client'; interface Team { id: string; name: string; } // Define the shape of the data returned by your GraphQL query interface Data { allTeams?: Team[]; } const GET_ALL_TEAMS = gql` query { allTeams { id name } } `; const SectionTable = () => ( <table className="table table-hover table-responsive"> <thead> <tr> <th scope="col">ID</th> <th scope="col">Name</th> <th scope="col">Actions</th> </tr> </thead> <tbody> <Query query={GET_ALL_TEAMS}> {/* Use QueryResult<Data> to type the render prop parameters */} {({ data = {}, error, loading }: QueryResult<Data>) => { // Safely destructure allTeams with fallbacks to avoid undefined errors const { allTeams = [] } = data; if (loading) { return <div>LOADING</div>; } if (error) { return <div>ERROR</div>; } return ( <> {allTeams.map(team => ( <tr key={team.id}> <td>{team.id}</td> <td>{team.name}</td> <td> {/* Add your action components here */} <button type="button">Edit</button> <button type="button">Delete</button> </td> </tr> ))} </> ); }} </Query> </tbody> </table> ); export default SectionTable;
Solution 2: Define a custom matching interface
If you prefer to use a custom interface instead of QueryResult, ensure it matches the structure the Query component expects:
interface SectionTableQueryProps { data?: Data; // Matches your Data interface error?: ApolloError; loading: boolean; // Add other Query properties like refetch/fetchMore if you need them }
Then use this interface in your render prop:
{({ data = {}, error, loading }: SectionTableQueryProps) => { // ... rest of your logic }}
Key Fixes Recap
- We moved
allTeamsback inside thedataobject, where theQuerycomponent actually provides it. - Using
QueryResult<Data>ensures TypeScript understands the exact shape of the fetched data. - Added fallbacks (
data = {}andallTeams = []) to safely handle cases where data might be undefined.
内容的提问来源于stack exchange,提问作者Uj Corb

