CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-plugin-react

React specific linting rules for ESLint

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

prop-validation-rules.mddocs/

Prop Types and Validation Rules

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.

Capabilities

PropTypes Definition Rules

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
};

PropTypes Organization Rules

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: ''
};

PropTypes Restrictions

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;
};

Component Props Interface

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"]
    }]
  }
}

PropTypes with Higher-Order Components

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 Patterns

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
    })
  )
};

PropTypes with TypeScript

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 Rule Configuration

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
    }]
  }
}

docs

code-style-rules.md

component-lifecycle-rules.md

index.md

jsx-syntax-rules.md

plugin-configuration.md

prop-validation-rules.md

react-component-rules.md

security-safety-rules.md

tile.json