-
-
Notifications
You must be signed in to change notification settings - Fork 30
Description
Describe the bug
prefer-read-only-props rule does not work well with extended types. Coming from a react-native/expo project we have a lot of the following code:
interface ComponentProps extends [NativeComponentProps] {
someProp: string
}
function Component(props: ComponentProps) {
const { someProp, ...nativeProps } = props;
}Where NativeComponentProps is say PressableProps or ViewProps. These come with react-native and of course aren't readonly so the rule fails.
I added a generic to force them to be read only like so:
type DeepReadOnly<T> = {
readonly [P in keyof T]: T[P] extends (infer U)[]
? ReadonlyArray<DeepReadOnly<U>>
: T[P] extends ReadonlyArray<infer U>
? ReadonlyArray<DeepReadOnly<U>>
: T[P] extends object
? DeepReadOnly<T[P]>
: T[P];
};
type ReadOnlyPressableProps = DeepReadOnly<Pressable>;However, while this appears to work when you inspect the types of ReadOnlyPressableProps, the eslint rule still reports the issue.
Reproduction
-
Clone eslint-plugin-react-x-prefer-read-only-props-false-negative
-
Run
npm install --force(required to ignore some peer dependency issues) -
Open in your editor
-
Open
src/Component.tsx -
You should now see an eslint warning that
Component's props are not readonly.
Alternatively, using eslint's cli: -
Clone eslint-plugin-react-x-prefer-read-only-props-false-negative
-
Run
npm install --force(required to ignore some peer dependency issues) -
Run
npm run lint
Expected behavior
No warning should be reported
Platform and versions
node -v
v22.14.0
{
"eslint": "^9.39.1",
"eslint-plugin-react-x": "^2.3.7",
"typescript-eslint": "^8.47.0"
}
Stack trace
Additional context
Note that if you use type instead of interface the issue seems to go away:
type DeepReadOnly<T> = {
readonly [P in keyof T]: T[P] extends (infer U)[]
? ReadonlyArray<DeepReadOnly<U>>
: T[P] extends ReadonlyArray<infer U>
? ReadonlyArray<DeepReadOnly<U>>
: T[P] extends object
? DeepReadOnly<T[P]>
: T[P];
};
interface PressableProps {
testID: string;
}
type ReadonlyPressableProps = DeepReadOnly<PressableProps>;
type ComponentProps = {
readonly name: string;
} & ReadonlyPressableProps;