Problem with rewriting toTS React HOC which limits visibility

Viewed 22

I have React HOC which restricts component visibility based on fixed prop

const RenderWhenIsVisible = Component => {
    return function (props) {
        let { isVisible, ...newProps } = props;
        return props.isVisible ? <Component {...newProps} /> : null;
    };
};

When try to rewrite to TS errors appear. Below is the version with lowest errors number, in the meantime I have passed through few others

interface isVisible {
    isVisible: boolean;
}
function RenderWhenIsVisible<T>(Component: React.ComponentType<T>) {
    return function (props: T & isVisible ) {
        let { isVisible, ...newProps} = props;
        return props.isVisible ? <Component {...newProps } /> : null;
    };
}

The error is:

Type 'Omit<T & isVisible, "isVisible">' is not assignable to type 'IntrinsicAttributes & T & { children?: ReactNode; }'. Type 'Omit<T & isVisible, "isVisible">' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'Omit<T & isVisible, "isVisible">'.

I understand that ...newProps shoud be clearly typed as T but have no idea how to pass such the declaration.

1 Answers

There are limits to what TypeScript can reason about when it's still dealing with unresolved type parameters such as T and conditional types such as Omit.

There are ways to get around this, in this case I would recommend, since we expect T and Omit<T & IsVisible, keyof IsVisible> to be the same type, to type the component as accepting either of those two types using a union. This shouldn't have a negative impact on the call site, and we can use newProps without any other issues:

interface IsVisible {
    isVisible: boolean;
}
function RenderWhenIsVisible<T>(Component: React.ComponentType<T | Omit<T & IsVisible, keyof IsVisible>>) {
    return function (props: T & IsVisible ) {
        let { isVisible, ...newProps} = props;
        return props.isVisible ? <Component {...newProps } /> : null;
    };
}

Playground Link

Related