relay
relay copied to clipboard
Relay 13: understanding the new Flow types
Hello! 👋 First and foremost, thanks for investing your energy into bringing the new Rust Compiler into OSS world as well. 👍
I have some questions regarding the new compiler and specifically regarding the new Flow types and how to use them. Could you please have a look and share with me if I am using it correctly or not? I feel like I am missing something important because the GraphQL tags are now annotated in the generated file precisely (which is awesome but I am not sure how to use it correctly). 🤔
useFragment
flowTypegen: {
phase: 'Final',
}
Before:
import type { ProductCreateFormData$key } from "./__generated__/ProductCreateFormData.graphql";
const data = useFragment<ProductCreateFormData$key>(graphql` … `);
After:
import type {
ProductCreateFormData$data,
ProductCreateFormData$fragmentType,
ProductCreateFormData$key, // used for prop annotation
} from './__generated__/ProductCreateFormData.graphql';
const data = useFragment<ProductCreateFormData$fragmentType, ProductCreateFormData$data>(graphql` … `);
Concern: the *.graphql.js
file already exports the fragment with the fragment type. Should users use it somehow?
module.exports = ((node/*: any*/)/*: Fragment<
ProductCreateFormData$fragmentType,
ProductCreateFormData$data,
>*/);
useMutation
Basically no change but only with:
flowTypegen: {
phase: 'Compat',
}
However, with phase: 'Final'
there is no *Mutation
type and the only exported types are *$variables
and *$data
. How should the "Final" phase be used together with useMutation
?
Similarly, usePreloadedQuery
also doesn't generate *Query
type in the "Final" phase that was previously used like this:
usePreloadedQuery<ProductsGridModalBodyQuery>(graphql` … `);
🤔
useLazyLoadQuery
Before:
import type { NavigationHeaderBadgeQuery } from "./__generated__/NavigationHeaderBadgeQuery.graphql";
const data = useLazyLoadQuery<NavigationHeaderBadgeQuery>(graphql` … `);
After:
import type {
NavigationHeaderBadgeQuery$data,
NavigationHeaderBadgeQuery$variables,
} from './__generated__/NavigationHeaderBadgeQuery.graphql';
const data = useLazyLoadQuery
NavigationHeaderBadgeQuery$variables,
NavigationHeaderBadgeQuery$data,
>(graphql` … `);
Is this the correct way how to use the new types?
Thank you very much for having a look! 😎
WOW! I just discovered that these new Flow types are directly supported by Flow! 🤯
So it seems like the expected way how to use Relay with Flow is to set the following in .flowconfig
:
relay_integration=true
relay_integration.module_prefix=./__generated__/
relay_integration.excludes=.*/__tests__/.*
relay_integration.excludes=.*/__flowtests__/.*
and basically, remove all manual generic types, so for example before:
const data = useLazyLoadQuery<NavigationHeaderBadgeQuery>(graphql` … `);
and after:
const data = useLazyLoadQuery(graphql` … `);
Which still type checks all the fields and everything correctly. Is this the idea? Well done! 😃
Is this the idea?
Yes, this is the main idea. We'll be updating the docs with instructions on how to use the new types.
cc @kassens
Will this be possible in Typescript too?
@RichardLindhout As far as we know the automatic understanding of GraphQL tags isn't possible in TypeScript. We worked directly with the Flow team to teach Flow how to understand GraphQL tags and the way Relay compiler (and the Babel plugin) cooperate to turn them into require calls. The translation is very straightforward (fragment Foo ...
turns into a require('Foo.graphql')
) but this does require explicit support from the type checker.
It would be amazing to see TypeScript support this, though!
@DanielRosenwasser is something like this possible in Typescript or is it possible with a plugin or something like that?