reactjs - როგორ გამოავლინოთ Apollo Query-ის ტიპი Typescript-ით
მეც ვცდილობ, რომ 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] ტიპს 'Data | undefined' არ აქვს საკუთრება 'allVendors' და არ აქვს სტრინგის ინდექსის სიგნატურა. რაც ხდება ამ ხაზზე: {({ 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 TypeScript-ის ტიპების შექმნისთვის როგორც სერვერისთვის (თქვენი სქემის მიხედვით), ასევე კლიენტისთვის (თქვენი სქემისა და GraphQL დოკუმენტების მიხედვით). ის ასევე ქმნის რეზოლვერების სიგნატურას და ძალიან პერსონალიზებადი არის.
თქვენ შეგიძლიათ სცადოთ ეს აქ: 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-ს data: { allVendors } პირველ კოდბლოკში, 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;
