Search code examples
reactjstypescriptreact-nativereact-functional-component

Generic and extension of component prop type


We have two React components (the 2nd one uses the 1st one in both props and rendering).

ReadOnlyField is defined as follow:

type ReadOnlyFieldProps<T> = {
  value: T;
  format: (value: T) => string;
  // ...rest
}

const ReadOnlyField = <T extends any>(props: ReadOnlyFieldProps<T>) => {
  return (); // render something
}

Now the EditableField uses the ReadOnlyField component:

type EditableFieldProps<T> = ReadOnlyFieldProps<T> & {
  onChange: (newValue: T) => void;
}

const EditableField = <T extends any>({ onChange, ...props}: EditableFieldProps<T>) => {
  return (<>
    <ReadOnlyField {...props} />
    {/* some other stuff */}
  </>);
}

Strangely typescript cannot infer generic type T of ReadOnlyProp based on provided value type inside EditableField. I receive the following error:

Type '{ value: T; format: ((value: T) => string); ... }' is not assignable to type 'ReadonlyFieldProps<unknown>'

Expo snack for TS error reproduction: https://snack.expo.dev/@signa89/react-native-ts-test (check EF.tsx).

How can I define the type of EditableFieldProps in a way

  1. to extend the type of ReadOnlyFieldProps
  2. and prevent the generic type of ReadOnlyField from being inferred as unknown ?

Note: I also tried using interfaces with no luck.


Solution

  • It seems that the problem was in exporting the parent component (ReadOnlyField) as a memo (i.e. export default React.memo(ReadOnlyField)). When I removed the memo function and exported it regularly (export default ReadOnlyField), the error is gone.