# How to Handle React PropTypes When Converting to TypeScript: A Migration Guide

> Migrate React PropTypes to TypeScript smoothly. Learn to manage existing propTypes during conversion, ensuring a seamless transition for your React application.

- Repository: [Meta/react](https://github.com/facebook/react)
- Tags: migration-guide
- Published: 2026-02-16

---

**Keep your existing `propTypes` definitions in place while adding TypeScript interfaces, then remove them gradually once your components are fully typed and tested.**

When migrating a React application from JavaScript to TypeScript, developers face the challenge of reconciling runtime **PropTypes** validation with compile-time static typing. According to the `facebook/react` source code, the framework supports a gradual transition where both systems can coexist safely, allowing teams to adopt TypeScript without breaking existing development workflows or losing runtime safety nets.

## Why React PropTypes and TypeScript Can Coexist During Migration

React’s core still actively reads `propTypes` from component definitions during development. In [`fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-runtime.development.js`](https://github.com/facebook/react/blob/main/fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-runtime.development.js) at line 1070, the runtime explicitly checks `type.propTypes` to validate props before rendering. This means your existing runtime checks continue to function exactly as before, catching accidental misuse in development builds while TypeScript handles static analysis at compile time.

## Step-by-Step Strategy for Handling React PropTypes in TypeScript

### 1. Preserve Existing PropTypes for Runtime Safety

Do not delete your `propTypes` definitions when you first add TypeScript. They provide immediate feedback in the browser console during development, which is valuable while you are still converting dependent components. The React repository’s own migration approach demonstrates that `propTypes` remain functional even as the codebase adopts stricter typing.

### 2. Add Parallel TypeScript Interfaces

Create an interface or type alias that mirrors your `propTypes` shape, then annotate the component’s props parameter. This gives you **compile-time** validation without removing the **runtime** safety net.

```typescript
import PropTypes from 'prop-types';
import type {FC} from 'react';

interface ButtonProps {
  label: string;
  onClick?: () => void;
}

const Button: FC<ButtonProps> = ({label, onClick}) => (
  <button onClick={onClick}>{label}</button>
);

// Runtime checks remain for legacy environments
Button.propTypes = {
  label: PropTypes.string.isRequired,
  onClick: PropTypes.func,
};

export default Button;

```

### 3. Configure ESLint to Allow Both Systems

The React repository disables the `react/prop-types` rule in its own [`.eslintrc.js`](https://github.com/facebook/react/blob/main/.eslintrc.js) at lines 188–190 to prevent the linter from flagging the temporary coexistence of both type systems. Apply the same configuration to your project to eliminate false positives while you transition.

```javascript
// .eslintrc.js
module.exports = {
  rules: {
    'react/prop-types': 'off',
  },
};

```

### 4. Gradually Remove PropTypes After TypeScript Validation

Once a component is fully typed and covered by tests, delete its `propTypes` definition. The official React [`CHANGELOG.md`](https://github.com/facebook/react/blob/main/CHANGELOG.md) at line 192 notes that `propTypes` will eventually be ignored and recommends moving to TypeScript or another static-type solution. This phased removal prevents regressions while cleaning up the codebase.

```typescript
import type {FC} from 'react';

interface ButtonProps {
  label: string;
  onClick?: () => void;
}

const Button: FC<ButtonProps> = ({label, onClick}) => (
  <button onClick={onClick}>{label}</button>
);

export default Button;

```

## Handling Edge Cases and Legacy Code

### Managing React.PropTypes Imports

If your legacy code uses `React.PropTypes`, you must migrate to the external `prop-types` package. The React [`CHANGELOG.md`](https://github.com/facebook/react/blob/main/CHANGELOG.md) entry for version 15.2.1 at line 1521 explains that `React.PropTypes` was moved to the separate `prop-types` package. Additionally, [`scripts/error-codes/codes.json`](https://github.com/facebook/react/blob/main/scripts/error-codes/codes.json) entry 84 contains the runtime error message triggered when `React.PropTypes` is accessed directly, confirming this separation.

```javascript
// Before (deprecated)
import React from 'react';
React.PropTypes.string;

// After (correct)
import PropTypes from 'prop-types';
PropTypes.string;

```

### Suppressing Duplicate Type Warnings

If TypeScript complains about duplicate type definitions when both systems are present, use a suppression comment until you remove the `propTypes` line.

```typescript
// @ts-ignore – temporary until PropTypes removal
Button.propTypes = {
  label: PropTypes.string.isRequired,
};

```

## Key Files in the React Source Code Supporting This Pattern

The `facebook/react` repository contains several files that demonstrate official support for this migration pattern:

- **[`fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-runtime.development.js`](https://github.com/facebook/react/blob/main/fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-runtime.development.js)** (line 1070) – Contains the runtime check that reads `type.propTypes` during component rendering, proving that PropTypes remain functional in modern React.

- **[`CHANGELOG.md`](https://github.com/facebook/react/blob/main/CHANGELOG.md)** (line 192) – Documents the recommendation to migrate from PropTypes to TypeScript or other static type solutions, and notes that PropTypes will eventually be ignored.

- **[`.eslintrc.js`](https://github.com/facebook/react/blob/main/.eslintrc.js)** (lines 188–190) – Shows the official React repository configuration that disables the `react/prop-types` ESLint rule, allowing both type systems to coexist during migration.

- **[`packages/react/src/__tests__/testDefinitions/PropTypes.d.ts`](https://github.com/facebook/react/blob/main/packages/react/src/__tests__/testDefinitions/PropTypes.d.ts)** – Provides a minimal TypeScript shim that allows the React test suite to compile while still importing from the `'prop-types'` package.

- **[`scripts/error-codes/codes.json`](https://github.com/facebook/react/blob/main/scripts/error-codes/codes.json)** (entry 84) – Contains the error message for deprecated `React.PropTypes` usage, confirming the separation of the PropTypes package from the core React library.

## Summary

- **Keep `propTypes` in place** when first adding TypeScript to maintain runtime validation during development, as React’s core still checks `type.propTypes` at runtime.
- **Add parallel TypeScript interfaces** to enforce compile-time contracts without removing the safety net that catches errors in the browser console.
- **Disable the `react/prop-types` ESLint rule** to prevent false positives while both systems coexist, following the pattern used in the React repository’s own [`.eslintrc.js`](https://github.com/facebook/react/blob/main/.eslintrc.js).
- **Migrate `React.PropTypes` imports** to the external `prop-types` package to avoid runtime errors, as the core React library no longer exports PropTypes directly.
- **Remove `propTypes` gradually** only after components are fully typed and tested, cleaning up the codebase once TypeScript provides complete static coverage.

## Frequently Asked Questions

### Should I remove React PropTypes immediately when adding TypeScript?

No, you should keep your existing `propTypes` definitions in place during the initial migration. They provide immediate runtime feedback in development builds while you are still converting dependent components and refining your TypeScript interfaces. Remove them only after a component is fully typed and covered by tests.

### Do PropTypes still run in development when using TypeScript?

Yes, React’s development build continues to validate `propTypes` at runtime regardless of whether you are using TypeScript. In [`fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-runtime.development.js`](https://github.com/facebook/react/blob/main/fixtures/legacy-jsx-runtimes/react-17/cjs/react-jsx-runtime.development.js) at line 1070, the React core explicitly checks `type.propTypes` during the rendering process, ensuring your runtime validations still catch errors in the browser console.

### How do I stop ESLint from complaining about missing PropTypes in TypeScript files?

Disable the `react/prop-types` rule in your ESLint configuration. The React repository itself uses this approach in [`.eslintrc.js`](https://github.com/facebook/react/blob/main/.eslintrc.js) at lines 188–190, setting `'react/prop-types': 'off'` to allow both TypeScript interfaces and `propTypes` definitions to coexist without linting errors during the migration period.

### Can I use both PropTypes and TypeScript interfaces permanently?

While technically possible, it is not recommended for production codebases. The React [`CHANGELOG.md`](https://github.com/facebook/react/blob/main/CHANGELOG.md) at line 192 indicates that `propTypes` will eventually be ignored in future releases and recommends moving to TypeScript or another static-type solution. Maintaining both systems long-term creates duplication, increases bundle sizes, and adds unnecessary maintenance overhead.