relay: Flow: property $refType is missing in object

Hello. πŸ‘‹ We use generated Flow types in our functions like this for example:

export default (room: ?BeddingInfo_room): string => {
  // ...
};

Problem is that Relay is generating Flow types with +$refType:

import type { ConcreteFragment } from 'relay-runtime';
import type { FragmentReference } from 'relay-runtime';
declare export opaque type BeddingInfo_room$ref: FragmentReference;
export type BeddingInfo_room = {|
  +type: ?string,
  +maxPersons: ?number,
  +bedding: ?$ReadOnlyArray<?{|
    +type: ?string,
    +amount: ?number,
  |}>,
  +$refType: BeddingInfo_room$ref,   // <<<
|};

This, unfortunately, complicates our testing because we cannot use simple plain objects (without the $refType):

expect(
  // Flow error here (vv) because Relay $refType is missing in the object
  formatBeddingInfo({
    type: 'Single Room',
    maxPersons: 1,
    bedding: [
      {
        type: 'Single Bed(s)',
        amount: 1,
      },
    ],
  }),
).toMatchSnapshot();

I don’t really understand why is this property necessary but is it possible to make it at least optional? Or how should we test it properly? It was fine before version 1.5… Error message:

Cannot call formatBeddingInfo with object literal bound to room because property $refType is missing in object
literal [1] but exists in BeddingInfo_room [2].

     app/hotels/src/singleHotel/roomList/__tests__/formatBeddingInfo.test.js
      4β”‚
      5β”‚ it('formats bedding information', () => {
      6β”‚   expect(
 [1]  7β”‚     formatBeddingInfo({
      8β”‚       type: 'Single Room',
      9β”‚       maxPersons: 1,
     10β”‚       bedding: [
     11β”‚         {
     12β”‚           type: 'Single Bed(s)',
     13β”‚           amount: 1,
     14β”‚         },
     15β”‚       ],
     16β”‚     }),
     17β”‚   ).toMatchSnapshot();
     18β”‚ });
     19β”‚

     app/hotels/src/singleHotel/roomList/formatBeddingInfo.js
 [2]  7β”‚ export default (room: ?BeddingInfo_room): string => {

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 10
  • Comments: 15 (8 by maintainers)

Commits related to this issue

Most upvoted comments

There is actually a workaround described in the relay doc:

Applied to a fragment definition, @relay(mask: false) changes the generated Flow types to be better usable when the fragment is included with the same directive. The Flow types will no longer be exact objects and no longer contain internal marker fields.

To be clear, you need to add @relay(mask: false) both when defining the fragment:

fragment Todo_todo on Todo @relay(mask: false)

and when using it:

...Todo_todo @relay(mask: false)

You will find a working example in this repository.

Hey, sorry for not responding here earlier.

To unblock your tests for now, you can do something like:

// Maybe define this in some utility
const mockRefType: any = null;

expect(
  // Flow error here (vv) because Relay $refType is missing in the object
  formatBeddingInfo({
    $refType: mockRefType,
    type: 'Single Room',
    maxPersons: 1,
    bedding: [
      {
        type: 'Single Bed(s)',
        amount: 1,
      },
    ],
  }),
).toMatchSnapshot();

I do think there should be more work done on testability and making the testing more ergonomic.

@sibelius it did not. Just upgraded from 1.4.1 to 2.0.0 and we have hundreds of these flow errors now. the mockRefType workaround that @kassens suggested works, but I can’t just go through each error and add this one by one. This is a big problem for us. The same goes for $fragmentRefs

@juhaelee, I think you wanted to mention @mrtnzlml πŸ˜ƒ

@mrmlnc I see, I also seemed to get flow errors on mutations as well ever since the upgrade πŸ˜•