Nozbe / withObservables

HOC (Higher-Order Component) for connecting RxJS Observables to React Components
https://github.com/Nozbe/WatermelonDB
MIT License
68 stars 26 forks source link

Typescript definition support #54

Closed bogdancochioras closed 5 years ago

bogdancochioras commented 5 years ago

Hello, I use this module with WatermelonDB, I tried to convert the Flow definition of withObservables to Typescript but it seems I am missing something any help appreciated:

`declare module '@nozbe/with-observables' {

import * as React from 'react';
import { Observable } from 'rxjs/Observable';

type UnaryFn<A, R> = (a: A) => R;
type HOC<Base, Enhanced> = UnaryFn<React.ComponentType<Base>, React.ComponentType<Enhanced>>;

type ObservableConvertible<T> = { readonly observe: () => Observable<T> };

type ExtractTypeFromObservable = <T>(value: Observable<T> | ObservableConvertible<T>) => T;

type $Values<O extends object> = O[keyof O];

type ObjMapper<T> = (value: $Values<Required<T>>, ...args: any[]) => any;

export type $ObjMap<T extends object, F extends ObjMapper<T>> = {
    [K in keyof T]: ReturnType<F>
};

type $Exact<T> = {
    [P in keyof T]: T[P]
};

type WithObservablesSynchronized<Props, ObservableProps> =
    HOC<$Exact<Props> & $ObjMap<ObservableProps, ExtractTypeFromObservable>, Props>;

type TriggerProps<A> = (keyof A)[] | null;

type GetObservables<A, B> = (props: A) => B;

export default function withObservables<Props, ObservableProps>(
    triggerProps: TriggerProps<Props>,
    getObservables: GetObservables<Props, ObservableProps>,
): WithObservablesSynchronized<Props, ObservableProps>;

}`

Example usage: `

export const enhanceAnElement =
    withObservables<{
        firstProp: Model
    }, {
        anObservable: Observable<Model>,
    }>(
        ['firstProp'],
        ({firstProp}) => {
            return {
                anObservable: firstProp.observe(),
            };
        }
    );

export const anElement = (props: {
    firstProp: Model,
    secondProp: string
}): JSX.Element => {
    return <View></View>;
};
export const enhancedElement = enhanceAnElement(anElement);

I receive the error Types of parameters 'props' and 'props' are incompatible. because withObservables expects all the props of the 'props' property from anElement but in enhanceAnElement only firstProp is defined so somehow the definition needs to allow other unused props that are not required in the enhancer, any idea what would need to be updated?