如何让 Typescript 识别 Apollo 查询的类型
How to make Typescript recognize the type for an Apollo Query
我正在尝试让 Apollo 与 TypeScript 集成。
我有一个 React Class,如下所示:
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);
两者有什么区别?如何重写第一条语句的类型?
由于您在第一个代码块中使用 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;
有一个小型库和一个 CLI 可以为服务器(根据您的架构)和客户端(根据您的架构和 GraphQL 文档)生成 TypeScript 类型。它还生成解析器签名并且非常可定制。
您可以在这里尝试:https://github.com/dotansimha/graphql-code-generator
这里有一篇关于该软件包的博客 post;
https://medium.com/the-guild/graphql-code-generator-for-typescript-react-apollo-7b225672588f
其背后的想法是允许开发人员充分利用 GraphQL 和生成的类型,并更轻松地自定义生成的输出。
它还可以根据您需要的类型生成 react-apollo 组件。
我正在尝试让 Apollo 与 TypeScript 集成。 我有一个 React Class,如下所示:
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);
两者有什么区别?如何重写第一条语句的类型?
由于您在第一个代码块中使用 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;
有一个小型库和一个 CLI 可以为服务器(根据您的架构)和客户端(根据您的架构和 GraphQL 文档)生成 TypeScript 类型。它还生成解析器签名并且非常可定制。
您可以在这里尝试:https://github.com/dotansimha/graphql-code-generator
这里有一篇关于该软件包的博客 post; https://medium.com/the-guild/graphql-code-generator-for-typescript-react-apollo-7b225672588f
其背后的想法是允许开发人员充分利用 GraphQL 和生成的类型,并更轻松地自定义生成的输出。
它还可以根据您需要的类型生成 react-apollo 组件。