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

- facebook/flow#8612
- gajus/eslint-plugin-flowtype#467
  • Loading branch information
mrtnzlml committed Apr 4, 2021
1 parent 8284425 commit f02b28f
Show file tree
Hide file tree
Showing 205 changed files with 540 additions and 534 deletions.
5 changes: 2 additions & 3 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# @generated SignedSource<<ae49cb9ae55943d5887942a3c1b7b525>>
# @generated SignedSource<<cc03860d3a8d355bd35e54f6ada88c23>>
#
# To regenerate run:
# yarn monorepo-babel-node scripts/generateFlow.js
Expand All @@ -24,10 +24,10 @@

[lints]
all=error
ambiguous-object-type=off
sketchy-null-bool=off
unclear-type=off
untyped-import=off
ambiguous-object-type=off

[options]
emoji=true
Expand All @@ -42,7 +42,6 @@ experimental.const_params=true
[rollouts]

[strict]
ambiguous-object-type
sketchy-null-bool
unclear-type
untyped-import
Expand Down
6 changes: 4 additions & 2 deletions .flowconfig.template.base
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,21 @@
; https://flow.org/en/docs/config/lints/
[lints]
all=error
ambiguous-object-type=off
sketchy-null-bool=off
unclear-type=off
untyped-import=off

# Flow standard is now to use `{ }` for strict objects and `{ key: value, ... }` for open objects,
# so this option should always be `off`.
ambiguous-object-type=off


; This setting complements [lints] section: all the enabled lints still throw errors + these
; additional lints are enabled only in strict mode (no need to list here every lint). Local
; strict mode behaves the same like strict mode except it turns off 'nonstrict-import' rule.
;
; https://flow.org/en/docs/strict/
[strict]
ambiguous-object-type
sketchy-null-bool
unclear-type
untyped-import
Expand Down
12 changes: 6 additions & 6 deletions src/__flowtests__/ReactElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@

import { Component, type Element, type ChildrenArray, type Node } from 'react';

class Button extends Component<{| +disabled?: boolean |}> {
class Button extends Component<{ +disabled?: boolean }> {
render() {
return null;
}
}

class DisabledButton extends Component<{||}> {
class DisabledButton extends Component<{}> {
// The return type is not necessary - it's here only to demonstrate what is going on.
render(): Element<typeof Button> {
return <Button disabled={true} />;
}
}

class WrapperLimited extends Component<{|
class WrapperLimited extends Component<{
+children: ChildrenArray<
// You have to specify every single supported component here.
Element<typeof Button> | Element<typeof DisabledButton>,
>,
|}> {}
}> {}

class WrapperSmart extends Component<{|
class WrapperSmart extends Component<{
// Type `RestrictedElement` understands what is being rendered so it accepts even `DisabledButton`(because it returns `Button`).
+children: ChildrenArray<RestrictedElement<typeof Button>>,
|}> {}
}> {}

module.exports.testStupid = ((
<WrapperLimited>
Expand Down
14 changes: 7 additions & 7 deletions src/__flowtests__/RestrictedElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import * as React from 'react';

// You can enforce compositional patterns with RestrictedElement:
class MenuItem extends React.Component<{||}> {}
class MenuSeparator extends React.Component<{||}> {}
class Menu extends React.Component<{|
class MenuItem extends React.Component<{}> {}
class MenuSeparator extends React.Component<{}> {}
class Menu extends React.Component<{
+children: React.ChildrenArray<
RestrictedElement<typeof MenuItem> | RestrictedElement<typeof MenuSeparator>,
>,
|}> {}
class NotAMenuComponent extends React.Component<{||}> {}
}> {}
class NotAMenuComponent extends React.Component<{}> {}

// All the children types allowed.
module.exports.test1 = ((
Expand All @@ -33,7 +33,7 @@ module.exports.test2 = ((
</Menu>
): React.Node);

class RendersAMenuItem extends React.Component<{||}> {
class RendersAMenuItem extends React.Component<{}> {
render(): React.Element<typeof MenuItem> {
return <MenuItem />;
}
Expand All @@ -47,7 +47,7 @@ module.exports.test3 = ((
</Menu>
): React.Node);

class RendersSomethingThatRendersAMenuItem extends React.Component<{||}> {
class RendersSomethingThatRendersAMenuItem extends React.Component<{}> {
// You really should just use RestrictedElement here, but I want
// to demonstrate the flexibility.
render(): React.Element<typeof RendersAMenuItem> {
Expand Down
2 changes: 1 addition & 1 deletion src/__flowtests__/lints/implicit-inexact-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
// flowlint ambiguous-object-type:off
export type A = { x: number };
export type B = { x: number, ... };
export type C = {| x: number |};
export type C = { x: number };
5 changes: 5 additions & 0 deletions src/eslint-config-adeira/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
- New accessibility rules enabled: [`jsx-a11y/anchor-has-content`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-has-content.md), [`jsx-a11y/heading-has-content`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md) and [`jsx-a11y/no-noninteractive-tabindex`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-noninteractive-tabindex.md) (warnings or errors in strict mode)
- Rule [`react/jsx-no-target-blank`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md) enabled (warnings or errors in strict mode)

TKTK (problem with `flowtype/require-readonly-react-props`)

- `flowtype/require-exact-type`
- `flowtype/require-inexact-type`

# 5.1.0

- New rule `relay/function-required-argument` enabled (warnings or errors in strict mode). See: https://github.com/relayjs/eslint-plugin-relay/pull/108
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ react/no-multi-comp

import { PureComponent, Component, useState, type Element } from 'react';

type LetterProps = {|
type LetterProps = {
+letter: string,
+onClick: () => void,
|};
};

const A = 65; // ASCII character code

Expand All @@ -23,12 +23,12 @@ class Letter extends PureComponent<LetterProps> {
}
}

type AplhabetProps = {||};
type AplhabetProps = {};

type AplhabetState = {|
type AplhabetState = {
justClicked: null | string,
letters: $ReadOnlyArray<string>,
|};
};

export class Alphabet1 extends Component<AplhabetProps, AplhabetState> {
constructor(props: AplhabetProps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { createContext, Component, type Node, type Context, type Element } from 'react';

type Props = {|
type Props = {
+accessToken?: string,
+children: Node,
|};
};

type State = {|
type State = {
accessToken: ?string,
|};
};

const MyContext: Context<State> = createContext({
accessToken: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const React = {
Component: class Component<S, P> {},
};

type Props = {||};
type State = {||};
type Props = {};
type State = {};

export default class MyComponent extends React.Component<void, State> {
props: Props;
Expand Down
4 changes: 2 additions & 2 deletions src/eslint-config-adeira/ourRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,9 @@ module.exports = ({
},
],
'flowtype/require-compound-type-alias': OFF,
'flowtype/require-exact-type': OFF,
'flowtype/require-exact-type': [NEXT_VERSION_ERROR, 'never'], // we are using `exact_by_default=true`
'flowtype/require-indexer-name': OFF,
'flowtype/require-inexact-type': ERROR,
'flowtype/require-inexact-type': OFF,
'flowtype/require-parameter-type': OFF,
'flowtype/require-readonly-react-props': ERROR,
'flowtype/require-return-type': OFF,
Expand Down
4 changes: 2 additions & 2 deletions src/eslint-fixtures-tester/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ export default function testFixtures({
rule,
validFixturesPath,
invalidFixturesPath,
}: {|
}: {
rule: EslintRule,
validFixturesPath: string,
invalidFixturesPath: string,
|}): void {
}): void {
const validFixtures = [];
const invalidFixtures = [];
for (const fixture of fs.readdirSync(validFixturesPath)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
* @flow strict
*/

type INode = {||};
type INode = {};

// should be wrapped in $ReadOnly<…>
export type Identifier1 = {|
export type Identifier1 = {
...INode,
+aaa: string,
|};
};

// should be wrapped in $ReadOnly<…>
export type Identifier2 = {|
export type Identifier2 = {
...INode,
+aaa: string,
+bbb: string,
|};
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// @flow strict

type INode = {||};
type INode = {};

export type Identifier1 = {|
export type Identifier1 = {
...INode,
name: string,
|};
};

export type Identifier2 = {|
export type Identifier2 = {
...INode,
name: string, // writable on purpose
+surname: string,
|};
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @flow strict

export type Identifier = {|
export type Identifier = {
+name: string,
|};
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// @flow strict

type INode = {||};
type INode = {};

export type Identifier1 = $ReadOnly<{|
export type Identifier1 = $ReadOnly<{
...INode,
+name: string,
|}>;
}>;

export type Identifier2 = $ReadOnly<{|
export type Identifier2 = $ReadOnly<{
...INode,
name: string, // writable on purpose
|}>;
}>;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// @flow strict

type INode = {||};
type INode = {};

export type Identifier = $ReadOnly<{|
export type Identifier = $ReadOnly<{
...INode,
-name: string,
|}>;
}>;
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import * as React from 'react';
import sx from '@adeira/sx';

type Props = {|
type Props = {
+children: React.Element<'strong'>,
|};
};

export default function IconButton({ children, ...props }: Props): React.Node {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import * as React from 'react';
import sx from '@adeira/sx';

type Props = {|
type Props = {
+children: React.Element<'strong'>,
|};
};

export default function IconButton({ children, ...props }: Props): React.Node {
return (
Expand Down
4 changes: 2 additions & 2 deletions src/example-relay/src/Homepage/locations/Location.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import Image from 'next/image';
import Text from '../../components/Text';
import type { Location$key } from './__generated__/Location.graphql';

type Props = {|
type Props = {
+location: ?Location$key,
+dataCount?: string,
|};
};

export default function Location(props: Props): Node {
const location = useFragment(
Expand Down
4 changes: 2 additions & 2 deletions src/example-relay/src/Homepage/locations/LocationsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import sx from '@adeira/sx';

import Location from './Location';

type Props = {|
type Props = {
+children: Element<typeof Location> | ChildrenArray<Element<typeof Location>>,
+start?: number,
|};
};

export default function LocationList({ children, start = 1 }: Props): Node {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import Location from './Location';
import LocationList from './LocationsList';
import type { LocationsPaginated_data as LocationsDataType } from './__generated__/LocationsPaginated_data.graphql';

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

function LocationsPaginated(props: Props) {
function loadMore() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import Location from './Location';
import LocationList from './LocationsList';
import type { LocationsPaginatedBidirectional_data as LocationsDataType } from './__generated__/LocationsPaginatedBidirectional_data.graphql';

type Props = {|
type Props = {
+itemsCount: number,
+data: LocationsDataType,
+relay: RefetchRelayProp,
|};
};

function LocationsPaginatedBidirectional(props: Props) {
const [start, setStart] = useState(1);
Expand All @@ -29,7 +29,7 @@ function LocationsPaginatedBidirectional(props: Props) {
return null; // or some failure placeholder
}

function handlePageChange(args: {| before?: ?string, after?: ?string |}, callback: () => void) {
function handlePageChange(args: { before?: ?string, after?: ?string }, callback: () => void) {
props.relay.refetch(
{
first: args.after != null ? props.itemsCount : null,
Expand Down
Loading

0 comments on commit f02b28f

Please sign in to comment.