Uh oh!
There was an error while loading. Please reload this page.
Enable Strict TS API by default (#57490) - #57490
Conversation
@huntie has exported this pull request. If you are a Meta employee, you can view the originating Diff in D110458670. |
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Description to come. Differential Revision: D110458670
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Description to come. Differential Revision: D110458670
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Description to come. Differential Revision: D110458670
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Finish tidying up description below. Differential Revision: D110458670
cortinico
left a comment
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) Exposes a `'react-native/react-private-interface'` subpath export on the main package, to replace `Libraries/ReactPrivate/ReactNativePrivateInterface.js`. **Impact: Internal** This is a private contract between `react` and `react-native`. - `ReactNativePrivateInterface` is deprecated and we'll migrate React call sites in a future version before cleanup. **Naming** Translate directly to `react-private-interface` ("private interface for React"). There's alternatives here but the explicitness and continuity is helpful, I believe. Changelog: [Internal] Reviewed By: robhogan Differential Revision: D111231527
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) Adds a `'react-native/unstable-internals-do-not-use'` entry point that acts as an explicit, opt-in escape hatch for frameworks and libraries that depend on specific React Native internals. Follows (and supersedes) react-native-community/discussions-and-proposals#985. Resolves T270727304. **Motivation** - Maintains a known list of which React Native internals are still in use. - Decouples removal of the Strict API opt-out from the longer-term decisions about these APIs. - Lets us relocate supporting source files freely, since consumers reference this subpath instead of deep internal paths. **Notes** - Reuses the runtime **object-with-getter pattern** (same as `index.js`), to avoid any native module side effects caused by loading adjacent file exports. - e.g. in Expo, [`hmrUtils.js`](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts?fbclid=IwY2xjawS7GjNwZG9mA2V4dG4DYWVtAjExAGJyaWQRMTZ1ckEwU05oWUw2bDBVN21zcnRjBmFwcF9pZAEwAAEen3UuX4Ig-RD3n1ULZIHIHq21Mfk_ci9b2SxquY7UkngDs6qhnRt5YQlb8Os_aem_ylJy40egSOl1qhZ9bA9HTA) is designed to be run early in RN startup — preserve the lazy require characteristic and do not break this. - TypeScript defs on this API are minimal, with complex internal input/handle types reduced to `unknown`. As with D110602194, these are intended to be feature-locked. **Exposed internals and known consumers** NOTE: The exports the community needs have reduced slightly since the spreadsheet in RFC0895 and would almost all align with `devsupport`. However, we're explicitly leaving a decision to formalise until later, and we may need to add in extra APIs quickly based on RC feedback. | Export | Source module | Known consumers | |---|---|---| | `AppContainer` | `Libraries/ReactNative/AppContainer` | react-native-screens ([DebugContainer.tsx](https://github.com/software-mansion/react-native-screens/blob/6f38d76129d40cc8145d06b98f885b508fa7bf2d/src/components/DebugContainer.tsx#L5)) | | `AssetSourceResolver` | `Libraries/Image/AssetSourceResolver` | Re.pack ([IncludeModules.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/IncludeModules.ts#L9)) | | `customDirectEventTypes` | `Libraries/Renderer/shims/ReactNativeViewConfigRegistry` | react-native-gesture-handler ([customDirectEventTypes.ts](https://github.com/software-mansion/react-native-gesture-handler/blob/ee147abf364bef48a02d3cf437572b4dddd30bec/packages/react-native-gesture-handler/src/handlers/customDirectEventTypes.ts#L2)) | | `DevLoadingView` | `Libraries/Utilities/DevLoadingView` | Expo ([hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts)), Re.pack ([WebpackHMRClient.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/WebpackHMRClient.ts)) | | `getDevServer` | `Libraries/Core/Devtools/getDevServer` | Expo ([getDevServer.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/getDevServer.native.ts), [hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts), [base.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/dom/base.ts), [getDevServer.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/metro-runtime/src/getDevServer.native.ts), [devServerEndpoints.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/log-box/src/utils/devServerEndpoints.ts), [getConnectionInfo.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/devtools/src/getConnectionInfo.native.ts), [index.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo-router/src/getDevServer/index.native.ts)) | | `HMRClient` | `Libraries/Utilities/HMRClient` | Expo ([metroServerLogs.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/metro-runtime/src/metroServerLogs.native.ts)) | | `NativeExceptionsManager` | `Libraries/Core/NativeExceptionsManager` | Expo ([hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts)), Re.pack ([WebpackHMRClient.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/WebpackHMRClient.ts)) | | `NativeRedBox` | `Libraries/NativeModules/specs/NativeRedBox` | Expo ([hmrUtils.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/async-require/hmrUtils.native.ts)), Re.pack ([WebpackHMRClient.ts](https://github.com/callstack/repack/blob/2498b3a426203daa4b81c7e6f7a88e86d88e77b9/packages/repack/src/modules/WebpackHMRClient.ts)) | | `NativeSourceCode` | `Libraries/NativeModules/specs/NativeSourceCode` | Expo ([getBundleUrl.native.ts](https://github.com/expo/expo/blob/2d07e3a17f4be2284bbf579d8825fe32f762ce1a/packages/expo/src/utils/getBundleUrl.native.ts)) | | `PressabilityDebugView` | `Libraries/Pressability/PressabilityDebug` | react-native-gesture-handler ([PressabilityDebugView.tsx](https://github.com/software-mansion/react-native-gesture-handler/blob/ee147abf364bef48a02d3cf437572b4dddd30bec/packages/react-native-gesture-handler/src/handlers/PressabilityDebugView.tsx#L2)) | **Alternative names** - `unstable-frameworks` - `unstable-devsupport` - `frameworks-private-interface` (mirroring `ReactPrivateInterface.js`) — this is likely a future stable shape candidate. Changelog: [Internal] Reviewed By: rubennorte Differential Revision: D110911864
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Finish tidying up description below. Reviewed By: cortinico Differential Revision: D110458670
This pull request has been merged in c948b61. |
Summary: Pull Request resolved: react#57490 See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) This is the **big switch** to enable the Strict TypeScript API (generated types + single index entry point) by default in React Native. **Opt-in → opt-out** After this change, the main `react-native` package resolves its `"types"` entry points only to `types_generated/index.d.ts` — with no other subpaths available. The new `"react-native-legacy-deep-imports"` condition maps to legacy `types/` and `Libraries/*.d.ts` sources. **Impact limitation**: For this stage of rollout, the `"default"` condition continues to resolve to source files. Only TypeScript is affected. **How to opt out** Opposite of today's opt-in, which we will update in [the docs](https://reactnative.dev/docs/strict-typescript-api). Again, the only impact area today is **TypeScript**. ```json5 // tsconfig.json { "extends": "react-native/typescript-config", "compilerOptions": { ... "customConditions": ["react-native-legacy-deep-imports"] } } ``` **Other changes** - Drop `react-native/typescript-config/strict` entry point, update README. - Update `__typetests__`. **Rollout plan** **Target release: 0.87**. This and the contributing stack will be cherry picked for RC1. - We've conducted testing against 100+ real Expo codebases, giving us the confidence that we've reduced breaking changes enough that the vast majority of RN codebases can migrate. - The Strict API includes a number of **intentional breaking changes**, and docs have been kept up to date. - We're shipping a `/migrate-to-strict-api` skill to migrate via agents, see react-native-community/skills#3. **What's improved since 0.80?** Since the initial opt-in launch of the Strict API in 0.80, we've been making continuous improvements over the last year to get our generated types into a widely launchable state. Most notably: - 21+ new/updated root APIs and fixes due to community feedback ([discussion](react-native-community/discussions-and-proposals#893), [PRs](https://github.com/react/react-native/pulls?q=is%3Apr%20label%3A%22JS%20API%20stabilization%20(1.0)%22%20is%3Aclosed)). - Upstream encapsulation blocker in TypeScript, fixed in 6.0 (react#53565). - Tailwind/Uniwind compatibility (`interface` types for props). - `*Instance` ref type exports for all built-in components (react-native-community/discussions-and-proposals#1003). - Fixes to previously mistyped, high impact APIs, such as `Appearance`. - New subpath entry points for `asset-registry`, `setup-env`, and others. - Refinements to doc comments/type translation build. **Rollback plan** Revert this diff. IMPORTANT: We'll adopt a policy of **super-eager rollback**, if there are any unsolvable issues during the RC phase. Changelog: [General][Breaking] - React Native's default JavaScript API is now the [Strict TypeScript API](https://reactnative.dev/docs/strict-typescript-api). Use `customConditions: ["react-native-legacy-deep-imports"]` to opt out. Reviewed By: cortinico Differential Revision: D110458670 fbshipit-source-id: 4b0e0b458a5f895f783d6d936e7b11ccff2df076
Summary: Pull Request resolved: #57490 See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) This is the **big switch** to enable the Strict TypeScript API (generated types + single index entry point) by default in React Native. **Opt-in → opt-out** After this change, the main `react-native` package resolves its `"types"` entry points only to `types_generated/index.d.ts` — with no other subpaths available. The new `"react-native-legacy-deep-imports"` condition maps to legacy `types/` and `Libraries/*.d.ts` sources. **Impact limitation**: For this stage of rollout, the `"default"` condition continues to resolve to source files. Only TypeScript is affected. **How to opt out** Opposite of today's opt-in, which we will update in [the docs](https://reactnative.dev/docs/strict-typescript-api). Again, the only impact area today is **TypeScript**. ```json5 // tsconfig.json { "extends": "react-native/typescript-config", "compilerOptions": { ... "customConditions": ["react-native-legacy-deep-imports"] } } ``` **Other changes** - Drop `react-native/typescript-config/strict` entry point, update README. - Update `__typetests__`. **Rollout plan** **Target release: 0.87**. This and the contributing stack will be cherry picked for RC1. - We've conducted testing against 100+ real Expo codebases, giving us the confidence that we've reduced breaking changes enough that the vast majority of RN codebases can migrate. - The Strict API includes a number of **intentional breaking changes**, and docs have been kept up to date. - We're shipping a `/migrate-to-strict-api` skill to migrate via agents, see react-native-community/skills#3. **What's improved since 0.80?** Since the initial opt-in launch of the Strict API in 0.80, we've been making continuous improvements over the last year to get our generated types into a widely launchable state. Most notably: - 21+ new/updated root APIs and fixes due to community feedback ([discussion](react-native-community/discussions-and-proposals#893), [PRs](https://github.com/react/react-native/pulls?q=is%3Apr%20label%3A%22JS%20API%20stabilization%20(1.0)%22%20is%3Aclosed)). - Upstream encapsulation blocker in TypeScript, fixed in 6.0 (#53565). - Tailwind/Uniwind compatibility (`interface` types for props). - `*Instance` ref type exports for all built-in components (react-native-community/discussions-and-proposals#1003). - Fixes to previously mistyped, high impact APIs, such as `Appearance`. - New subpath entry points for `asset-registry`, `setup-env`, and others. - Refinements to doc comments/type translation build. **Rollback plan** Revert this diff. IMPORTANT: We'll adopt a policy of **super-eager rollback**, if there are any unsolvable issues during the RC phase. Changelog: [General][Breaking] - React Native's default JavaScript API is now the [Strict TypeScript API](https://reactnative.dev/docs/strict-typescript-api). Use `customConditions: ["react-native-legacy-deep-imports"]` to opt out. Reviewed By: cortinico Differential Revision: D110458670 fbshipit-source-id: 4b0e0b458a5f895f783d6d936e7b11ccff2df076
## Description Since React Native 0.87, Strict TS API is [enabled by default ](react/react-native#57490). This PR brings necessary changes to resolve ts-errors on 0.87. This PR also removes `cursor: undefined;` from `iOS`, but now it is a valid prop - this workaround was necessary on old arch ## Test plan `yarn ts-check`
- 0.88.0-nightly-20260720-e64027865 - react/react-native@e04ff69...e640278 - Bump RN deps and devDeps (@react-native: babel/jest preset, eslint/metro/ts configs) - Bump Jest snapshot test rendered RN ver - Update lockfiles (Yarn, CocoaPods) - Update iOS privacy manifest - Bump ReadMe ver - Opt out of RN default Strict TS API for RNsafeareacontext - react/react-native#57490 - #2041 - @lavamoat/react-native-lockdown unaffected by - react/react-native#57482 deprecated rn-get-polyfills unused - react/react-native#57475 - only hooking into Metro serializer opts getPolyfills and getRunModuleStatement - react-native/packages/community-cli-plugin: getModulesRunBeforeMainModule updated from /Libraries/Core/InitializeCore to /setup-env in core Resolve: #2031
- react/react-native#57490 example overwrites react-native by mistake - preserve react-native config like github.com/react/react-native/tree/main/packages/typescript-config
jakebailey
commented
Aug 18, 2026
This broke a lot of DefinitelyTyped packages: DefinitelyTyped/DefinitelyTyped#75402 In particular, changing from interfaces to type aliases means that the types can no longer be extended, which breaks I don't think that interfaces are really any less strict than type aliases, and are a breaking change for any types out there using the fact that they're interfaces. Would you consider undoing some of this? |
huntie
commented
Aug 19, 2026
@jakebailey Which version did you test and which types collided? This is something we directly addressed in 0.87 — and if there's extra gaps, we can adjust. |
jakebailey
commented
Aug 19, 2026
DT is unpinned, so it's the latest. If you look at https://github.com/DefinitelyTyped/DefinitelyTyped/actions/runs/32138113480, all failures (except maybe one or two) are due to react-native. The PR linked above shows the full set, but mainly it's react-native-web that has the problem. |
Summary:
See RFC0894: Removing deep imports from react-native
This is the big switch to enable the Strict TypeScript API (generated types + single index entry point) by default in React Native.
Opt-in → opt-out
After this change, the main
react-nativepackage resolves its"types"entry points only totypes_generated/index.d.ts— with no other subpaths available.The new
"react-native-legacy-deep-imports"condition maps to legacytypes/andLibraries/*.d.tssources.Impact limitation: For this stage of rollout, the
"default"condition continues to resolve to source files. Only TypeScript is affected.How to opt out
Opposite of today's opt-in, which we will update in the docs. Again, the only impact area today is TypeScript.
Other changes
@react-native/typescript-config/strictentry point, update README.__typetests__.Rollout plan
Target release: 0.87. This and the contributing stack will be cherry picked for RC1.
/migrate-to-strict-apiskill to migrate via agents, see Add migrate-to-strict-api skill react-native-community/skills#3.What's improved since 0.80?
Since the initial opt-in launch of the Strict API in 0.80, we've been making continuous improvements over the last year to get our generated types into a widely launchable state.
Most notably:
react-native/Libraries/*#53565).interfacetypes for props).*Instanceref type exports for all built-in components (RFC: Add dedicated Instance types for built-in component refs (JS API stabilization) react-native-community/discussions-and-proposals#1003).Appearance.asset-registry,setup-env, and others.Rollback plan
Revert this diff.
IMPORTANT: We'll adopt a policy of super-eager rollback, if there are any unsolvable issues during the RC phase.
Changelog:
[General][Breaking] - React Native's default JavaScript API is now the Strict TypeScript API. Use
customConditions: ["react-native-legacy-deep-imports"]to opt out.Reviewed By: cortinico
Differential Revision: D110458670