Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all articles
Browse latest Browse all 6287

Is it possible to create a strictly typed React HOC in Typescript?

$
0
0

As context, I'm attempting to create a higher order component to wrap React Native components and add some functionality based on a ref to the component.

Short, untyped example:

export function withHelper(WrappedEl) {  return ({    layoutParam,    onChangeLayout,    ...wrappedElProps  }) => {    const ref = useRef(null);    const onLayout = useCallback(() => {      ref.current?.measure((_x, _y, width, height, px, py) => {        onChangeLayout({          layout: {            width,            height,            y: py,            x: px,          },          layoutParam,        });      });    }, [      onChangeLayout,      layoutParam,    ]);    return <WrappedEl {...wrappedElProps} ref={ref} onLayout={onLayout} />;  };}

measure is a React Native element that gives me some information I need about the element for rendering other things. It's from the interface NativeMethods.

What I'd like to get strictly typed here:

  • The HOC can only be used on elements that have the measure method.
  • The resulting component is appropriately typed with all the original component's props as well as the two added props (layoutParam and onChangeLayout).

This is how far I got:

interface WithHelperProps {  layoutParam: string;  onChangeLayout: (props: {layout: Layout, payoutParam: string}) => void;}export function withHelper<  P extends object,  V extends React.ComponentClass<P> & Constructor<NativeMethods>,>(El: V): React.FC<P & WithHelperProps> {  return ({    layoutParam,    onChangeLayout,    ...props  }) => {    const ref = useRef<InstanceType<V>>(null);    const onLayout = useCallback(() => {      ref.current?.measure((_x, _y, width, height, px, py) => {        onChangeLayout({          layout: {            width,            height,            y: py,            x: px,          },          layoutParam,        });      });    }, [      onChangeLayout,      layoutParam,    ]);    const passthroughProps: Omit<      PropsWithChildren<P & WithHelperProps>,      keyof WithHelperProps> = props;    return <El {...passthroughProps} ref={ref} onLayout={onLayout} />;  };}

But this doesn't compile:

Type 'Omit<PropsWithChildren<P & WithHelperProps>, keyof WithHelperProps> & { ref: RefObject<InstanceType<V>>; onLayout: () => void; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<P, any, any> & NativeMethods> & LibraryManagedAttributes<...>'.  Type 'Omit<PropsWithChildren<P & WithHelperProps>, keyof WithHelperProps> & { ref: RefObject<InstanceType<V>>; onLayout: () => void; }' is not assignable to type 'LibraryManagedAttributes<V, Readonly<P>>'.

I've been playing with it for a while and searching around, but I can't figure out what I'm doing wrong here.


I made a minimal reproduction in Replit.


Viewing all articles
Browse latest Browse all 6287

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>