Skip to content

Commit

Permalink
Flow: use implicit exact object types
Browse files Browse the repository at this point in the history
Flow standard is now to use `{ }` for strict objects and `{ key: value, ... }` for open objects, see: facebook/relay@6fa0b0d and facebook/react-native@00cfb0f

This change should be without any problems as longs as users of our NPM libraries are using Flow with `exact_by_default=true` (which is now pretty standard I'd say).

Here is how object types behave before this change:

```
type A = { x: number }; // already "exact" type but disallowed because it would be confusing to mix different syntaxes
type B = { x: number, ... }; // this is inexact
type C = {| x: number |}; // this is explicitly exact and the only allowed way how to describe type "exactness"
```

Here is how object types behave _after_ this change:

```
type A = { x: number }; // this is the only allowed syntax for "exact" type
type B = { x: number, ... }; // this is still inexact
type C = {| x: number |}; // this is also exact but no longer allowed (so it's not confusing)
```

Some related (non-blocking) issues:

- gajus/eslint-plugin-flowtype#467
- facebook/flow#8612

adeira-source-id: 5f0c905ae627f670804581f78c1b570f3f71a1e6
  • Loading branch information
mrtnzlml authored and adeira-github-bot committed Apr 8, 2021
1 parent e45faa0 commit 505c43f
Show file tree
Hide file tree
Showing 35 changed files with 97 additions and 95 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

Note for all Flow users: all projects in [`adeira/universe`](https://github.com/adeira/universe) now use implicit exact Flow types (`{}` for strict objects and `{ ... }` for open objects, syntax `{||}` is deprecated). We do not expect any issues as long as you are using `exact_by_default=true` Flow option.

# 3.2.2

- Added experimental bin `adeira-relay-compiler-experimental` which directly calls official `relay-compiler-experimental` bin. This new Relay compiler written in Rust is unstable (as the name suggests) but eventually will be the default. For now, you can start experimenting with it and report any issues to [`facebook/relay`](https://github.com/facebook/relay) repo.
Expand Down
12 changes: 6 additions & 6 deletions src/LocalQueryRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ import type { GraphQLTaggedNode } from 'relay-runtime';
import createLocalEnvironment from './createLocalEnvironment';
import type { Variables } from './types.flow';

type CommonProps = {|
type CommonProps = {
+query: GraphQLTaggedNode,
+environment?: Environment,
+variables?: Variables,
|};
};

type Props<T> =
| $ReadOnly<{|
| $ReadOnly<{
...CommonProps,
+onResponse: (T) => Node,
+onLoading?: () => Node,
|}>
| $ReadOnly<{|
}>
| $ReadOnly<{
...CommonProps,
+render: ({ +props: ?T, ... }) => Node,
|}>;
}>;

// Please note: we are currently only wrapping this component to add it correct Flow types.
// Eventually, it can be extended with other functions like original QueryRenderer.
Expand Down
16 changes: 8 additions & 8 deletions src/QueryRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@ import type { CacheConfig, GraphQLTaggedNode } from 'relay-runtime';

import type { Variables } from './types.flow';

type ReadyState<T> = {|
type ReadyState<T> = {
+error: ?Error,
+props: T,
+retry: ?() => void,
|};
};

type FetchPolicy = 'store-and-network' | 'network-only';

type CommonProps = {|
type CommonProps = {
+query: GraphQLTaggedNode,
+environment?: Environment,
+cacheConfig?: CacheConfig,
+fetchPolicy?: FetchPolicy,
+variables?: Variables,
|};
};

type Props<T> =
| $ReadOnly<{|
| $ReadOnly<{
...CommonProps,
+onSystemError?: ({
error: Error,
Expand All @@ -38,11 +38,11 @@ type Props<T> =
}) => Node,
+onLoading?: () => Node,
+onResponse: (T) => Node,
|}>
| $ReadOnly<{|
}>
| $ReadOnly<{
...CommonProps,
+render: (ReadyState<?T>) => Node,
|}>;
}>;

export default function QueryRenderer<T>(props: $ReadOnly<Props<T>>): Node {
function renderQueryRendererResponse({ error, props: rendererProps, retry }: ReadyState<?T>) {
Expand Down
4 changes: 2 additions & 2 deletions src/__flowtests__/ContainerType.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import {
type RefetchContainerType,
} from '../index';

type Props = {|
type Props = {
+aaa: string,
+bbb: number,
|};
};

function DefaultComponent(props) {
return <div {...props} />;
Expand Down
4 changes: 2 additions & 2 deletions src/__flowtests__/CustomQueryRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ function placeholder() {
return null;
}

type Props = {|
type Props = {
+query: GraphQLTaggedNode,
+render: () => Node,
|};
};

function CustomQueryRenderer(props: Props) {
const environment = createLocalEnvironment();
Expand Down
2 changes: 1 addition & 1 deletion src/__flowtests__/Disposable.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { graphql, requestSubscription, type RelayProp, type Disposable } from '../index';

type Props = {| +relay: RelayProp |};
type Props = { +relay: RelayProp };

type SubscriptionTypeMock = any;

Expand Down
12 changes: 6 additions & 6 deletions src/__flowtests__/Environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import {
type RelayProp,
} from '../index';

type PropsA = {| +relay: RelayProp |};
type PropsB = {| +relay: RefetchRelayProp |};
type PropsC = {| +relay: PaginationRelayProp |};
type PropsA = { +relay: RelayProp };
type PropsB = { +relay: RefetchRelayProp };
type PropsC = { +relay: PaginationRelayProp };

type PropsInvalid = {|
+relay: {| environment: number |},
|};
type PropsInvalid = {
+relay: { environment: number },
};

// this returns Environment which should never be used directly
const ManuallyCreatedEnvironment = createEnvironment({
Expand Down
2 changes: 1 addition & 1 deletion src/__flowtests__/createFragmentContainer-missingProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export default (createFragmentContainer(FunctionalFragmentExport, {
__typename
}
`,
}): FragmentContainerType<{||}>);
}): FragmentContainerType<{}>);
8 changes: 4 additions & 4 deletions src/__flowtests__/createFragmentContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ function getTestCases(Container) {
};
}

type Props = {|
type Props = {
+relay: RelayProp,
+data: {|
+data: {
+required: string,
+$refType: any,
|},
},
+fun?: (string) => void,
|};
};

const FunctionalComponent = (props: Props) => <div {...props} />;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ export default (createPaginationContainer(
}
`,
},
): PaginationContainerType<{||}>);
): PaginationContainerType<{}>);
4 changes: 2 additions & 2 deletions src/__flowtests__/createPaginationContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { useEffect } from 'react';

import { createPaginationContainer, graphql, type PaginationRelayProp } from '../index';

type Props = {|
type Props = {
+relay: PaginationRelayProp,
|};
};

module.exports = ({
validUsage() {
Expand Down
2 changes: 1 addition & 1 deletion src/__flowtests__/createRefetchContainer-missingProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ export default (createRefetchContainer(
...createRefetchContainerMissingProps_data
}
`,
): RefetchContainerType<{||}>);
): RefetchContainerType<{}>);
4 changes: 2 additions & 2 deletions src/__flowtests__/createRefetchContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

import { createRefetchContainer, graphql, type RefetchRelayProp } from '../index';

type Props = {|
type Props = {
+relay: RefetchRelayProp,
|};
};

module.exports = ({
validUsage() {
Expand Down
22 changes: 11 additions & 11 deletions src/__flowtests__/mutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ const variables = {
someEnum: 'up',
};

type NamedMutationVariables = {|
type NamedMutationVariables = {
+someNumber: number,
+someEnum: 'down' | 'up',
|};
};

type NamedMutationResponse = {|
+commitMutation: ?{|
type NamedMutationResponse = {
+commitMutation: ?{
+__typename: 'CommitMutationResponse',
|},
|};
},
};

type NamedMutation = {|
type NamedMutation = {
+variables: NamedMutationVariables,
+response: NamedMutationResponse,
|};
};

module.exports = {
validMutation(): Disposable {
Expand Down Expand Up @@ -86,13 +86,13 @@ module.exports = {
mutation,
variables,
// $FlowExpectedError[prop-missing]: response type differs from onCompleted declaration
onCompleted: (response: {||}) => {}, // eslint-disable-line no-unused-vars
onCompleted: (response: {}) => {}, // eslint-disable-line no-unused-vars
});
},
invalidAsyncMutation(): Promise<{|
invalidAsyncMutation(): Promise<{
+errors: ?$ReadOnlyArray<Error>,
+response: $ElementType<NamedMutation, 'response'>,
|}> {
}> {
// $FlowExpectedError[prop-missing]: onCompleted is disabled in config for commitMutationAsync
return commitMutationAsync<NamedMutation>(environment, {
mutation,
Expand Down
8 changes: 4 additions & 4 deletions src/__flowtests__/useLazyLoadQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ const query = graphql`
}
`;

type QueryTypeMock = {|
+variables: {||},
+response: {||},
|};
type QueryTypeMock = {
+variables: {},
+response: {},
};

module.exports = {
validUsage: (): (() => void) => {
Expand Down
4 changes: 2 additions & 2 deletions src/__flowtests__/useMutation.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ module.exports = {
validUsage: (): (() => void) => {
return function TestComponent() {
const [executeMutation, isMutationPending] = useMutation(mutation);
(executeMutation: ({|
(executeMutation: ({
onCompleted: () => void,
|}) => Disposable);
}) => Disposable);
(isMutationPending: boolean);

executeMutation({
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/createFragmentContainer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Component } from 'react';

import createFragmentContainer from '../createFragmentContainer';

class MockComponent extends Component<{||}> {}
class MockComponent extends Component<{}> {}

it('throws when used with empty fragment spec', () => {
let error = new Error();
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/createPaginationContainer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Component } from 'react';

import createPaginationContainer from '../createPaginationContainer';

class MockComponent extends Component<{||}> {}
class MockComponent extends Component<{}> {}

it('throws when used with empty fragment spec', () => {
let error = new Error();
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/createRefetchContainer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Component } from 'react';

import createRefetchContainer from '../createRefetchContainer';

class MockComponent extends Component<{||}> {}
class MockComponent extends Component<{}> {}

it('throws when used with empty fragment spec', () => {
let error = new Error();
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/buildLanguagePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { find } from 'relay-compiler/lib/language/javascript/FindGraphQLTags'; /

import formatGeneratedModule from './formatGeneratedModule';

type LanguagePlugin = {|
type LanguagePlugin = {
+inputExtensions: $ReadOnlyArray<string>,
+outputExtension: string,
+typeGenerator: $FlowFixMe,
+formatModule: $FlowFixMe,
+findGraphQLTags: $FlowFixMe,
|};
};

export default function buildLanguagePlugin(): LanguagePlugin {
return {
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/buildWatchExpression.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

type WatchmanConfig = $ReadOnlyArray<string | WatchmanConfig>;

export default function buildWatchExpression(config: {|
export default function buildWatchExpression(config: {
extensions: $ReadOnlyArray<string>,
include: $ReadOnlyArray<string>,
exclude: $ReadOnlyArray<string>,
|}): WatchmanConfig {
}): WatchmanConfig {
// https://facebook.github.io/watchman/docs/install.html
return [
'allof',
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/formatGeneratedModule.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// @flow strict

type FormatModuleInput = $ReadOnly<{|
type FormatModuleInput = $ReadOnly<{
documentType: $FlowFixMe,
concreteText: string,
typeText: string,
sourceHash: string,
devOnlyAssignments?: string,
docText?: string,
hash?: string,
|}>;
}>;

export default function formatGeneratedModule({
documentType,
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import buildWatchExpression from './buildWatchExpression';
import createPrintRequireDefaultModuleDependency from './createPrintRequireDefaultModuleDependency';
import getSchemaSource from './getSchemaSource';

type ExternalOptions = {|
type ExternalOptions = {
+src: string,
+schema: string,
+validate: boolean,
+watch: boolean,
+persistMode?: 'fs', // TODO consider more generic: +persistFunction?: ?(query: string) => Promise<string>,
|};
};

const {
commonTransforms,
Expand Down
4 changes: 2 additions & 2 deletions src/createEnvironment.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import createRelayStore from './createRelayStore';
import createRequestHandler from './createRequestHandler';
import RelayLazyLogger from './loggers/RelayLazyLogger';

type Options = {|
type Options = {
+fetchFn: (...args: $ReadOnlyArray<any>) => any,
+subscribeFn?: (...args: $ReadOnlyArray<any>) => any,
+handlerProvider?: (string) => void,
+operationLoader?: OperationLoader,
+records?: ?RecordObjectMap,
+gcReleaseBufferSize?: ?number,
+log?: LogFunction,
|};
};

function createNetwork(
fetchFn: (...args: $ReadOnlyArray<any>) => any,
Expand Down
4 changes: 2 additions & 2 deletions src/createFragmentContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { invariant, isObjectEmpty } from '@adeira/js';

import type { FragmentSpec, $RelayProps } from './types.flow';

export type RelayProp = {|
export type RelayProp = {
+environment: Environment,
|};
};

/**
* @deprecated use `useFragment` instead
Expand Down
Loading

0 comments on commit 505c43f

Please sign in to comment.