#Correct type for a "selector" in react props

5 messages · Page 1 of 1 (latest)

timber ridge
#

Hi,
I'm tryng to create a react component that accepts a selector as a prop, like many stata management libraries do.

type ReSubscribeProps<T> = {
    selector: (value: T) => any;
    children: (subscribedValue: ReturnType<ReSubscribeProps<T>['selector']>) => ReactNode;
};

export function ReSubscribe<T>(props: ReSubscribeProps<T>) {
    // Hooks
    const value = useFormValue<T>();

    // Memos
    const subscribedValue = useMemo(() => props.selector(value), [value, props.selector]);

    // Render
    return props.children(subscribedValue);
}

This is my attempt, but I'm having an hard time understanding how should I type this.
I want the user to be able to define any function, that takes a value: T as input and infer the return type.

The return type should then be used to render the children.

Here is an example of usage

type User = {
    name: string,
    email: string
}

<Resubscribe<User> selector={value => value.email.length > 3}>
    {isMoreThan3 => (isMoreThan3 ? <div>More than 5</div> : <div>Less thatn 5</div>)}
</Resubscribe>

In this case, isMoreThan3 is reported by intellisense as any, i would like it to be boolean.

I think this should be possibile, it's the same concept tanstack/forms is using.
I think the solution might be here (https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx), but I can't understand

steep stone
#

@timber ridge You'd use a generic for this:

type ReSubscribeProps<T, R> = {
    selector: (value: T) => R;
    children: (subscribedValue: R) => ReactNode;
};
#

In general when you're try to connect parts of a type to say that they're related, that's a case for generics.

timber ridge
#

With this approcch, should not be R mandatory?
Then i will not be able to use <Resubscribe /> without specifying the R generic

steep stone
#

TS infers genetics by default, you shouldn't usually be specifying them manually.