Enable Strict TS API by default (#57490)#57490
Closed
huntie wants to merge 3 commits into
Closed
Conversation
|
@huntie has exported this pull request. If you are a Meta employee, you can view the originating Diff in D110458670. |
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Jul 9, 2026
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Description to come. Differential Revision: D110458670
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Jul 9, 2026
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Description to come. Differential Revision: D110458670
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Jul 9, 2026
Summary: See [**RFC0894: Removing deep imports from react-native**](react-native-community/discussions-and-proposals#894) TODO: Description to come. Differential Revision: D110458670
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Jul 9, 2026
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
approved these changes
Jul 10, 2026
cortinico
left a comment
Contributor
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
cc19a4a to
0441eec
Compare
|
This pull request has been merged in c948b61. |
huntie
added a commit
to huntie/react-native
that referenced
this pull request
Jul 10, 2026
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
This was referenced Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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