如何让 Typescript 识别 Apollo 查询的类型
Posted
技术标签:
【中文标题】如何让 Typescript 识别 Apollo 查询的类型【英文标题】:How to make Typescript recognize the type for an Apollo Query 【发布时间】:2018-11-24 19:52:38 【问题描述】:我正在尝试让 Apollo 与 TypeScript 集成。 我有一个如下所示的 React 类:
interface Data
allVendors: Array<VendorType>;
class AllVendorsQuery extends Query<Data>
const ShowVendors: React.SFC<> = props =>
return (
<AllVendorsQuery query=fetchVendors>
( loading, error, data: allVendors ) =>
if (loading)
return 'Loading...';
if (error)
return `Error! $error.message`;
return (
allVendors &&
allVendors.map((vendor, index: number) =>
return (
<div key=`$vendor.name_$index`>
#<strong>vendor.id</strong>
vendor.name
</div>
);
)
);
</AllVendorsQuery>
);
;
export default ShowVendors;
查询是:
export default gql`
query GetVendors
allVendors
id
name
`;
TypeScript 抱怨 [ts] Type 'Data | undefined' has no property 'allVendors' and no string index signature.
出现在这一行:( loading, error, data: allVendors )
。
但是,如果我使用 apollo-connect
而不是 Query 组件重构代码,我不会收到来自 TypeScript 的任何抱怨:
import graphql, compose, QueryResult from 'react-apollo';
interface ShowVendorsProps
data: QueryResult & allVendors?: VendorType[] ;
class ShowVendors extends React.Component<ShowVendorsProps>
render()
const
data: allVendors
= this.props;
if (allVendors && allVendors.length > 0)
return (
<div>
allVendors.map((vendor, index: number) =>
return (
<div key=`$vendor.name_$index`>
#<strong>vendor.id</strong>
vendor.name
</div>
);
)
</div>
);
else
return 'Loading';
export default compose(graphql(fetchVendors))(ShowVendors);
这两者有什么区别?如何重写第一条语句的类型?
【问题讨论】:
【参考方案1】:有一个小型库和 CLI 可以为服务器(根据您的架构)和客户端(根据您的架构和 GraphQL 文档)生成 TypeScript 类型。它还生成解析器签名并且非常可定制。
你可以在这里试试:https://github.com/dotansimha/graphql-code-generator
这里有一篇关于该软件包的博文; https://medium.com/the-guild/graphql-code-generator-for-typescript-react-apollo-7b225672588f
其背后的想法是让开发人员充分利用 GraphQL 和生成的类型,并更轻松地自定义生成的输出。
它还可以生成带有您需要的类型的 react-apollo 组件。
【讨论】:
【参考方案2】:由于您在第一个代码块中使用data: allVendors
解构data
,TypeScript 会抱怨因为data
可能未定义,例如当数据仍在加载时。
因此,如果 TS 不抱怨,您可以在加载检查后进行解构,默认值为 allVendors
,类似于:
interface Data
allVendors: Array<VendorType>;
class AllVendorsQuery extends Query<Data>
const ShowVendors: React.SFC<> = props =>
return (
<AllVendorsQuery query=fetchVendors>
( loading, error, data ) =>
if (loading)
return 'Loading...';
if (error)
return `Error! $error.message`;
// If data is not undefined, then it sets allVendors accordingly.
// Otherwise it sets it to null (which you check for anyways below)
const allVendors = data || allVendors: null;
return (
allVendors &&
allVendors.map((vendor, index: number) =>
return (
<div key=`$vendor.name_$index`>
#<strong>vendor.id</strong>
vendor.name
</div>
);
)
);
</AllVendorsQuery>
);
;
export default ShowVendors;
【讨论】:
以上是关于如何让 Typescript 识别 Apollo 查询的类型的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Apollo 工具为查询生成 Typescript 类型,包括 Apollo @client 和 @rest 指令?
如何在 TypeScript 中使用 Apollo Client 自定义钩子?
如何使用 apollo 客户端从 schema.graphql 中提取 typescript 接口:codegen
使用 react-apollo,如何使用 TypeScript 在同一个组件中定义 2 个突变?
如何在 TypeScript 中为 React Apollo Query 组件编写 HOC?
如何在 Firestore Cloud Functions 上使用 Apollo Server GraphQL 在 TypeScript 中处理身份验证