Rules for PropTypes usage, prop validation, and type safety in React components. These rules ensure proper component interfaces and help catch prop-related errors during development.
Rules for defining and using PropTypes in React components.
const propTypesRules = {
/** Prevent missing props validation in React component definition */
'react/prop-types': ESLintRule;
/** Enforce all defaultProps have a corresponding non-required PropType */
'react/default-props-match-prop-types': ESLintRule;
/** Enforce a defaultProps definition for every prop that is not required */
'react/require-default-props': ESLintRule;
/** Prevent unused propTypes */
'react/no-unused-prop-types': ESLintRule;
/** Forbid certain propTypes */
'react/forbid-prop-types': ESLintRule;
};Usage Examples:
import PropTypes from 'prop-types';
// ✓ Good - Component with proper PropTypes
const UserCard = ({ name, age, email, isActive }) => {
return (
<div>
<h3>{name}</h3>
<p>Age: {age}</p>
<p>Email: {email}</p>
{isActive && <span>Active User</span>}
</div>
);
};
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
email: PropTypes.string,
isActive: PropTypes.bool
};
UserCard.defaultProps = {
email: '',
isActive: false
};
// ✗ Bad - Missing PropTypes
const UserCard = ({ name, age, email, isActive }) => {
return (
<div>
<h3>{name}</h3>
<p>Age: {age}</p>
</div>
);
};
// No PropTypes defined
// ✗ Bad - PropTypes don't match defaultProps
const MyComponent = ({ title, count }) => <div>{title}: {count}</div>;
MyComponent.propTypes = {
title: PropTypes.string.isRequired,
count: PropTypes.number
};
MyComponent.defaultProps = {
title: 'Default', // Error: title is required but has default
count: 0,
extra: 'unused' // Error: extra not in PropTypes
};Rules for organizing and sorting PropTypes definitions.
const propTypesOrganizationRules = {
/** Enforce propTypes declarations alphabetical sorting */
'react/sort-prop-types': ESLintRule;
/** Enforce defaultProps declarations alphabetical sorting */
'react/sort-default-props': ESLintRule;
/** Enforce JSX default props alphabetical sorting */
'react/jsx-sort-default-props': ESLintRule;
};Usage Examples:
// ✓ Good - PropTypes in alphabetical order
MyComponent.propTypes = {
age: PropTypes.number,
email: PropTypes.string,
name: PropTypes.string.isRequired,
role: PropTypes.oneOf(['admin', 'user'])
};
MyComponent.defaultProps = {
age: 0,
email: '',
role: 'user'
};
// ✗ Bad - PropTypes not alphabetically sorted
MyComponent.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
role: PropTypes.oneOf(['admin', 'user']),
email: PropTypes.string
};
MyComponent.defaultProps = {
role: 'user',
age: 0,
email: ''
};Rules for restricting certain PropTypes patterns that can lead to issues.
const propTypesRestrictionRules = {
/** Forbid certain propTypes (any, array, object) */
'react/forbid-prop-types': ESLintRule;
/** Forbid foreign propTypes */
'react/forbid-foreign-prop-types': ESLintRule;
/** Prevent object type as default prop */
'react/no-object-type-as-default-prop': ESLintRule;
/** Enforce exact prop types */
'react/prefer-exact-props': ESLintRule;
/** Enforce read-only props */
'react/prefer-read-only-props': ESLintRule;
};Usage Examples:
// ✓ Good - Specific PropTypes instead of generic ones
MyComponent.propTypes = {
user: PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
email: PropTypes.string
}),
items: PropTypes.arrayOf(PropTypes.string),
config: PropTypes.objectOf(PropTypes.string)
};
// ✗ Bad - Generic PropTypes (when forbidden)
MyComponent.propTypes = {
user: PropTypes.object, // Too generic
items: PropTypes.array, // Too generic
data: PropTypes.any // Too generic
};
// ✓ Good - Primitive default props
MyComponent.defaultProps = {
count: 0,
title: 'Default Title',
isVisible: false
};
// ✗ Bad - Object/array as default prop (creates new instance each time)
MyComponent.defaultProps = {
items: [], // New array each render
config: {}, // New object each render
user: { name: '' } // New object each render
};
// ✓ Good - Using exact prop types (Flow/TypeScript)
type Props = {|
name: string,
age: number
|};
// ✓ Good - Read-only props (TypeScript)
type Props = {
readonly name: string;
readonly age: number;
};Rules for component prop interface definition and validation.
const propsInterfaceRules = {
/** Forbid component props */
'react/forbid-component-props': ESLintRule;
/** Forbid DOM props */
'react/forbid-dom-props': ESLintRule;
/** Prevent passing of children as props */
'react/no-children-prop': ESLintRule;
};Usage Examples:
// ✓ Good - Using children prop correctly
const Container = ({ children, className }) => (
<div className={className}>
{children}
</div>
);
<Container className="wrapper">
<p>Child content</p>
</Container>
// ✗ Bad - Passing children as prop
<Container children={<p>Child content</p>} />
// ✓ Good - Allowed component props
<MyComponent
title="Hello"
onAction={handleAction}
data={items}
/>
// ✗ Bad - Forbidden component props (when configured)
<MyComponent
style={{ color: 'red' }} // Forbidden if style is restricted
className="my-class" // Forbidden if className is restricted
/>
// Configuration example:
{
"rules": {
"react/forbid-component-props": ["error", {
"forbid": ["style", "className"]
}],
"react/forbid-dom-props": ["error", {
"forbid": ["id", "style"]
}]
}
}Rules for handling PropTypes in HOCs and component composition.
const hocPropTypesRules = {
/** Handle propTypes in HOCs correctly */
'react/forbid-foreign-prop-types': ESLintRule;
};Usage Examples:
// ✓ Good - HOC that properly handles PropTypes
const withAuth = (WrappedComponent) => {
const AuthenticatedComponent = (props) => {
if (!isAuthenticated()) {
return <LoginPrompt />;
}
return <WrappedComponent {...props} />;
};
// Properly copy PropTypes
AuthenticatedComponent.propTypes = WrappedComponent.propTypes;
AuthenticatedComponent.displayName = `withAuth(${WrappedComponent.displayName || WrappedComponent.name})`;
return AuthenticatedComponent;
};
// ✗ Bad - Accessing foreign PropTypes directly
const MyComponent = ({ name }) => <div>{name}</div>;
const AnotherComponent = () => {
// Don't access PropTypes from other components
const nameType = MyComponent.propTypes.name;
return <div>Type: {nameType}</div>;
};Advanced PropTypes usage patterns and validations.
const advancedPropTypesRules = {
/** Custom PropTypes validation */
customValidators: PropTypesValidators;
};
interface PropTypesValidators {
/** Custom validator functions */
(props: any, propName: string, componentName: string): Error | null;
}Usage Examples:
// ✓ Good - Custom PropTypes validators
const customEmailValidator = (props, propName, componentName) => {
const value = props[propName];
if (value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
return new Error(
`Invalid prop \`${propName}\` of value \`${value}\` supplied to \`${componentName}\`, expected a valid email address.`
);
}
return null;
};
MyComponent.propTypes = {
email: customEmailValidator,
age: (props, propName, componentName) => {
const value = props[propName];
if (value && (value < 0 || value > 120)) {
return new Error(
`Invalid prop \`${propName}\` of value \`${value}\` supplied to \`${componentName}\`, expected age between 0 and 120.`
);
}
return null;
}
};
// ✓ Good - Complex PropTypes with oneOfType
MyComponent.propTypes = {
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Date)
]),
callback: PropTypes.func.isRequired,
items: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
name: PropTypes.string.isRequired,
optional: PropTypes.bool
})
)
};Integration patterns when using PropTypes alongside TypeScript.
// ✓ Good - TypeScript interfaces with PropTypes for runtime validation
interface UserProps {
name: string;
age: number;
email?: string;
isActive?: boolean;
}
const User: React.FC<UserProps> = ({ name, age, email = '', isActive = false }) => {
return (
<div>
<h3>{name}</h3>
<p>Age: {age}</p>
{email && <p>Email: {email}</p>}
{isActive && <span>Active</span>}
</div>
);
};
// Runtime PropTypes validation (optional with TypeScript)
User.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
email: PropTypes.string,
isActive: PropTypes.bool
};PropTypes rules support extensive configuration options:
{
"rules": {
"react/prop-types": ["error", {
"ignore": ["children", "className", "style"],
"customValidators": ["myCustomValidator"],
"skipUndeclared": false
}],
"react/require-default-props": ["error", {
"forbidDefaultForRequired": true,
"ignoreFunctionalComponents": false
}],
"react/forbid-prop-types": ["error", {
"forbid": ["any", "array", "object"],
"checkContextTypes": true,
"checkChildContextTypes": true
}],
"react/sort-prop-types": ["error", {
"ignoreCase": true,
"callbacksLast": false,
"requiredFirst": false,
"sortShapeProp": true,
"noSortAlphabetically": false
}],
"react/no-unused-prop-types": ["error", {
"customValidators": ["myCustomValidator"],
"skipShapeProps": true
}]
}
}