mirror of
https://github.com/react/react-native.git
synced 2026-09-28 13:23:09 +08:00
Enable Strict TS API by default (#57490)
Summary: Pull Request resolved: https://github.com/react/react-native/pull/57490 See [**RFC0894: Removing deep imports from react-native**](https://github.com/react-native-community/discussions-and-proposals/pull/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 https://github.com/react-native-community/skills/pull/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](https://github.com/react-native-community/discussions-and-proposals/discussions/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 (https://github.com/react/react-native/issues/53565). - Tailwind/Uniwind compatibility (`interface` types for props). - `*Instance` ref type exports for all built-in components (https://github.com/react-native-community/discussions-and-proposals/pull/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 commit is contained in:
@@ -471,9 +471,9 @@ jobs:
|
||||
- name: Flow
|
||||
shell: bash
|
||||
run: yarn flow-check
|
||||
- name: TypeScript
|
||||
- name: TypeScript (legacy deep imports / manual types)
|
||||
shell: bash
|
||||
run: yarn test-typescript
|
||||
run: yarn test-typescript-legacy
|
||||
|
||||
test_js:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@
|
||||
"test-release-local-clean": "node ./scripts/release-testing/test-release-local-clean.js",
|
||||
"test-release-local": "node ./scripts/release-testing/test-release-local.js",
|
||||
"test-ios": "./scripts/objc-test.sh test",
|
||||
"test-typescript": "tsc -p packages/react-native/types/tsconfig.json",
|
||||
"test-generated-typescript": "tsc -p packages/react-native/types_generated/tsconfig.test.json",
|
||||
"test-typescript-legacy": "tsc -p packages/react-native/__typetests__/tsconfig.legacy.json",
|
||||
"test-generated-typescript": "tsc -p packages/react-native/__typetests__/tsconfig.json",
|
||||
"test": "jest",
|
||||
"fantom": "./scripts/fantom.sh",
|
||||
"fantom-cli": "./scripts/fantom-cli.sh",
|
||||
|
||||
+3
-4
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"lib": ["es2020"],
|
||||
@@ -9,9 +10,7 @@
|
||||
"jsx": "react",
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"paths": {"react-native": ["."]},
|
||||
"moduleResolution": "bundler",
|
||||
"customConditions": ["react-native-strict-api"]
|
||||
"moduleResolution": "bundler"
|
||||
},
|
||||
"include": ["**/*.d.ts", "../__typetests__/**/*"]
|
||||
"include": ["**/*"]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
// Legacy variant: Opts into the `"react-native-legacy-deep-imports"` export
|
||||
// condition so `react-native` and `react-native/Libraries/*` resolve to the
|
||||
// hand-written types in `types/`.
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"customConditions": ["react-native-legacy-deep-imports"]
|
||||
}
|
||||
}
|
||||
@@ -27,20 +27,19 @@
|
||||
"react-native": "cli.js"
|
||||
},
|
||||
"main": "./index.js",
|
||||
"types": "types",
|
||||
"exports": {
|
||||
".": {
|
||||
"react-native-strict-api": "./types_generated/index.d.ts",
|
||||
"types": "./types/index.d.ts",
|
||||
"react-native-legacy-deep-imports": "./types/index.d.ts",
|
||||
"types": "./types_generated/index.d.ts",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./Libraries/*": {
|
||||
"react-native-strict-api": null,
|
||||
"types": "./Libraries/*.d.ts",
|
||||
"react-native-legacy-deep-imports": "./Libraries/*.d.ts",
|
||||
"types": null,
|
||||
"default": "./Libraries/*.js"
|
||||
},
|
||||
"./Libraries/*.js": {
|
||||
"react-native-strict-api": null,
|
||||
"types": null,
|
||||
"default": "./Libraries/*.js"
|
||||
},
|
||||
"./scripts/*": "./scripts/*",
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"strict": false,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": true,
|
||||
"types": [],
|
||||
"jsx": "react",
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"paths": {"react-native": ["."]}
|
||||
},
|
||||
"include": ["**/*.d.ts", "../__typetests__/**/*"]
|
||||
}
|
||||
@@ -9,25 +9,18 @@ This package provides the default `tsconfig.json` used by newly built React Nati
|
||||
|
||||
This template is customized for specific versions of React Native, and should be updated in sync with the rest of your app.
|
||||
|
||||
## Strict TypeScript API
|
||||
## Opting out of the Strict TypeScript API (default in 0.87)
|
||||
|
||||
To opt into the new [strict TypeScript API](https://reactnative.dev/blog/2025/06/12/moving-towards-a-stable-javascript-api#strict-typescript-api-opt-in) you can extend from `@react-native/typescript-config/strict`
|
||||
To opt out of the new [Strict TypeScript API](https://reactnative.dev/docs/strict-typescript-api) you can extend from `@react-native/typescript-config/strict`
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"extends": "@react-native/typescript-config/strict",
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
or alternatively add the `customConditions` yourself:
|
||||
If your app still needs access to deep `'react-native/Libraries/*'` imports (deprecated in 0.80), you can opt out via `customConditions` in your `tsconfig.json`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"extends": "@react-native/typescript-config",
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
"customConditions": ["react-native-strict-api", "react-native"]
|
||||
"customConditions": ["react-native", "react-native-legacy-deep-imports"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
],
|
||||
"bugs": "https://github.com/react/react-native/issues",
|
||||
"exports": {
|
||||
".": "./tsconfig.json",
|
||||
"./strict": "./tsconfig.strict.json"
|
||||
".": "./tsconfig.json"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "./tsconfig.json",
|
||||
"display": "React Native (Strict)",
|
||||
"compilerOptions": {
|
||||
"customConditions": ["react-native-strict-api", "react-native"]
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,8 @@
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"react-native-strict-api": "./types_generated/index.d.ts",
|
||||
"types": "./index.d.ts",
|
||||
"react-native-legacy-deep-imports": "./index.d.ts",
|
||||
"types": "./types_generated/index.d.ts",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./*": {
|
||||
|
||||
@@ -55,26 +55,10 @@ async function buildGeneratedTypes(): Promise<Set<string>> {
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
fs.copyFile(
|
||||
path.join(__dirname, 'templates', 'tsconfig.json'),
|
||||
path.join(
|
||||
PACKAGES_DIR,
|
||||
'react-native',
|
||||
TYPES_OUTPUT_DIR,
|
||||
'tsconfig.json',
|
||||
),
|
||||
),
|
||||
fs.copyFile(
|
||||
path.join(__dirname, 'templates', 'tsconfig.test.json'),
|
||||
path.join(
|
||||
PACKAGES_DIR,
|
||||
'react-native',
|
||||
TYPES_OUTPUT_DIR,
|
||||
'tsconfig.test.json',
|
||||
),
|
||||
),
|
||||
]);
|
||||
await fs.copyFile(
|
||||
path.join(__dirname, 'templates', 'tsconfig.json'),
|
||||
path.join(PACKAGES_DIR, 'react-native', TYPES_OUTPUT_DIR, 'tsconfig.json'),
|
||||
);
|
||||
|
||||
if (allErrors.length > 0) {
|
||||
console.error(
|
||||
|
||||
@@ -81,7 +81,7 @@ try {
|
||||
);
|
||||
|
||||
describe('Test: TypeScript tests');
|
||||
execAndLog(`${YARN_BINARY} run test-typescript`);
|
||||
execAndLog(`${YARN_BINARY} run test-typescript-legacy`);
|
||||
} catch (e) {
|
||||
if (e instanceof ExecError) {
|
||||
console.error(e.message);
|
||||
|
||||
Reference in New Issue
Block a user