Open
Description
I know there are other issues related to $Diff, but I wanted to lay out a particular use case that would eliminate a lot of the pain of using flow to type higher order functions and React components.
Current Scenario
Currently, flow forces you to manually diff objects, exemplified by the Translator
HOC in the libdef for react-i18next:
declare type Translator<OP, P> = {
(component: StatelessComponent<P>): Class<React$Component<void, OP, void>>;
<Def, St>(component: Class<React$Component<Def, P, St>>): Class<React$Component<Def, OP, St>>;
}
(this was in modeled after react-redux's Connector, which could probably also benefit from $Diff)
And it's usage:
type Props = { a: string }
type PropsWithT = Props & { t: TFunction }
const MyComponent = (props: PropsWithT) => /* something */
const translator: Translator<Props, PropsWithT> = translate('something')
const WrappedComp = translator(MyComponent)
// doesn't complain about missing props.t
<WrappedComp a="string" />
Notice how you have to pass in props for the HOC and for the original component?
Ideal Scenario
Ideally, you could use $Diff to do that work for you:
declare type Translator<P> = {
(component: StatelessComponent<P>): Class<React$Component<void, $Diff<P, { t: TFunction }>, void>>;
<Def, St>(component: Class<React$Component<Def, P, St>>): Class<React$Component<Def, $Diff<P, { t: TFunction }>, St>>;
}
Usage then becomes:
type Props = { a: string, t: TFunction }
const MyComponent = (props: Props) => /* something */
const translator: Translator<Props> = translate('something')
const WrappedComp = translator(MyComponent)
// doesn't complain about missing props.t
<WrappedComp a="string" />
Non-React HOF
An example of where $Diff could be used to type generic higher order functions:
type Obj = {
a: string,
b: string
}
const fn = (obj: Obj) => obj.a + obj.b
const hof = <Obj>(
fn: (obj: Obj) => string
): (obj: $Diff<Obj, { b: string }>) => string => {
return (obj) => fn({ ...obj, b: 'b' })
}
const fn2 = hof(fn)
// doesn't complain about missing obj.b
fn2({ a: 'a' })