The short version: on a fresh React Native 0.88.1 app with React Navigation 7.5, Reanimated 4.7, Gesture Handler 3.4, Keychain, MMKV and Zod, TypeScript 7.0.2 type-checks the whole project in a median of 0.27 s against 1.54 s for TypeScript 6.0.3, with half the peak memory, and it reports zero new errors. The 0.88 template’s tsconfig is already TS 7 clean. What does break is the older tsconfig.json that most apps started on React Native 0.6x or 0.7x still carry (moduleResolution: node plus baseUrl), and typescript-eslint, which refuses TS 7.0 outright until the new API lands in 7.1. Measured on 28 Oct 2026 in a Linux container (2 vCPU, Node 22.23.4), not on a Mac, so take the absolute times as a ratio rather than a target.
Why we did this: our Beacon-type banking apps run CI type-checks on every pull request, and those checks are the slowest step after the native builds. TypeScript 7.0 shipped on 8 July 2026 as the Go port previously previewed as tsgo, which Microsoft says is 8 to 12x faster on full builds, and the Type Server Protocol repo that will drive editor support was on the Hacker News front page this week. Before touching a client project we wanted a number from our own stack, and a list of what to change in tsconfig.json.
The setup
Everything below ran on 28 Oct 2026 in a Linux container with 2 vCPU, 8 GB RAM, Node 22.23.4 and npm 10.9.9. The app was created with @react-native-community/cli 20.2.0 against React Native 0.88.1 (released 27 Oct 2026), then given the libraries a banking app of ours actually uses:
react-native 0.88.1, react 19.3.0
@react-navigation/native 7.5.1, native-stack, bottom-tabs
react-native-reanimated 4.7.1, react-native-worklets 0.13.1
react-native-gesture-handler 3.4.0, react-native-screens 4.30.0
react-native-keychain 10.0.0, react-native-mmkv 4.3.2, zod 4.6.7
typescript 6.0.3 (the template default) and typescript 7.0.2
On top of the template we wrote about 300 lines of typed app code: a RootStackParamList with typed route params, a Zod statement schema with inferred types, an MMKV preferences store, Keychain session storage with biometric access control, and a BalanceCard that uses Reanimated shared values and a Gesture Handler tap. Small, but it exercises the generics that usually hurt: navigation prop types, z.infer, worklet-annotated callbacks and the strict React Native API that 0.87 made the default.
The 0.88.1 template pins "typescript": "^6.0.3". To run both compilers side by side we aliased TS 7 under a second name:
npm install -D ts7@npm:typescript@7.0.2
# tsc 6: node node_modules/typescript/bin/tsc --noEmit -p tsconfig.json
# tsc 7: node_modules/ts7/bin/tsc --noEmit -p tsconfig.json
One trap we hit immediately: both packages install a tsc binary, and npm let the alias overwrite node_modules/.bin/tsc, so npx tsc --version printed 7.0.2 while node_modules/typescript was still 6.0.3. Call the binaries by path, or use Microsoft’s @typescript/typescript6 package, which exposes tsc6 instead of fighting over the name.
The timing
tsc --noEmit covers 942 files once you count the type declarations pulled in from node_modules. We ran each compiler five times, alternating, and took the median wall time; peak memory is the resident set size of an isolated run, read through getrusage. The script is 30 lines of Python and is at the end of the post.

Median of five runs per compiler on the same 942-file project; TS 7 with and without its default four checker threads.
compiler median min max peak RSS
tsc 6.0.3 (typescript, JS on Node v22.23.4) 1.54s 1.48s 1.62s 250 MB
tsc 7.0.2 (typescript, native Go) 0.27s 0.27s 0.29s 126 MB
tsc 7.0.2 --singleThreaded 0.26s 0.26s 0.28s 106 MB
That is 5.7x faster and half the memory. Microsoft’s own table shows 7.7x to 11.9x on VS Code, Sentry, Bluesky, Playwright and tldraw; our ratio is lower because the project is tiny and a good share of the 1.5 s on TS 6 is Node starting up and loading the compiler, a fixed cost that the Go binary does not pay. The --singleThreaded row is the interesting one for CI: on 2 vCPU the four default checker threads buy nothing, so if you run on small runners you can drop the extra memory for free. On a real app with 2,000 of your own files the ratio will move toward Microsoft’s numbers, not away from them.
--extendedDiagnostics on TS 7 breaks the 0.25 s down as 0.094 s parse, 0.043 s bind and 0.106 s check for 29,989 types and 102,771 instantiations.
What breaks: nothing in the template, four things in old projects
With the 0.88.1 template’s tsconfig.json, which just extends @react-native/typescript-config, TS 7 reported no errors at all. That is not luck. The 0.88 config already uses moduleResolution: bundler, customConditions: ["react-native"], strict: true, esModuleInterop: true and an explicit types: ["jest"], which are exactly the settings TS 7 either requires or now defaults to. The React Native team did this work in 0.87 when they made the strict TypeScript API the default and published the generated types under the react-native export condition.
Apps that were created on React Native 0.6x or early 0.7x and never regenerated their tsconfig.json are a different story. We kept a copy of that era’s config and ran both compilers against it:

Left, the tsconfig.json shape from the old react-native-template-typescript; right, the same file after the four changes TS 7 forced.
TypeScript 6.0.3 already flags the old config, but as deprecations you can silence:
error TS5107: Option 'moduleResolution=node10' is deprecated and will stop functioning in TypeScript 7.0.
error TS5101: Option 'baseUrl' is deprecated and will stop functioning in TypeScript 7.0.
Specify compilerOption '"ignoreDeprecations": "6.0"' to silence this error.
TypeScript 7.0.2 turns them into hard stops, and adds two more:
tsconfig.legacy.json(11,25): error TS5108: Option 'moduleResolution=node10' has been removed.
tsconfig.legacy.json(12,5): error TS5102: Option 'baseUrl' has been removed. Use '"paths": {"*": ["./*"]}' instead.
tsconfig.legacy.json(13,33): error TS5090: Non-relative paths are not allowed. Did you forget a leading './'?
tsconfig.legacy.json(13,65): error TS5090: Non-relative paths are not allowed. Did you forget a leading './'?
The fix is mechanical: switch to "moduleResolution": "bundler", delete baseUrl, prefix every paths entry with ./, and add "customConditions": ["react-native"] so you get the strict API types instead of the legacy ones. After that, TS 7 produced exactly one remaining error, in __tests__/App.test.tsx:
error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner?
That one is a TS 7 default change rather than a removal: types now defaults to [] instead of “every @types package in node_modules“, so Jest’s globals disappear unless you list them. "types": ["jest"] fixed it and the check came back clean. If you also rely on @types/node globals in scripts, add node to the same list.
There is a second reason to do this before touching TS 7. With moduleResolution: node and deprecations silenced, TypeScript 6.0.3 cannot see React Native 0.88’s types at all, because they live behind a package.json exports map:
error TS7016: Could not find a declaration file for module 'react-native'.
There are types at '.../react-native/types_generated/index.d.ts', but this result could not be
resolved under your current 'moduleResolution' setting. Consider updating to 'node16', 'nodenext', or 'bundler'.
So on 0.88 the old config already costs you every React Native type, silently turning View, FlatList and friends into any. We saw TS7006 Parameter 'a' implicitly has an 'any' type show up in our own reduce callback purely because of this. Fixing the resolution setting is worth doing for 0.88 on its own, regardless of the TS 7 move.
typescript-eslint and Metro
TypeScript 7.0 ships without a programmatic API; Microsoft expects a new one in 7.1. That matters for anything that imports the compiler, and in a React Native project that means @typescript-eslint/parser, which @react-native/eslint-config uses for every .ts and .tsx file. With TS 6.0.3 installed as typescript, npx eslint src/App.tsx ran normally (one react-native/no-inline-styles warning). We then made typescript resolve to the 7.0.2 package and ran it again:

typescript-eslint 8.72.1 refuses to start when typescript resolves to 7.0.2, and points at the TS 6 side-by-side setup.
typescript-eslint does not support TS 7.0.
Please see https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0
See also https://github.com/typescript-eslint/typescript-eslint/issues/10940 for tracking typescript-eslint's support for TS >=7.1
Oops! Something went wrong! :(
Metro is the opposite case. It strips types with Babel and never loads the TypeScript package (a grep of metro*/src for require('typescript') finds nothing), so with only TS 7 installed, npx react-native bundle --platform android --dev false still produced a 1.84 MB release bundle. Jest is the same, through babel-jest.
The arrangement that works today, and the one we are adopting, is the one Microsoft documents: keep TypeScript 6 as the typescript package so the linter, editor plugins and tsc6 keep working, and alias TypeScript 7 for the type-check step:
{
"devDependencies": {
"typescript": "npm:@typescript/typescript6@^6.0.2",
"@typescript/native": "npm:typescript@^7.0.2"
},
"scripts": {
"typecheck": "node_modules/@typescript/native/bin/tsc --noEmit",
"lint": "eslint ."
}
}
When typescript-eslint ships 7.1 support, the alias goes away and typescript moves to 7.
What we are changing in our apps
Three things, in this order. First, regenerate tsconfig.json from @react-native/typescript-config on every app that still has moduleResolution: node or baseUrl, because that config is already losing React Native’s types on 0.88. Second, add TS 7 as the aliased typecheck script in CI, where a 5x to 10x drop on the slowest non-native step is worth the one extra dev dependency. Third, leave the linter and editors on TS 6 until typescript-eslint supports 7.1, and revisit when it does.
One honest limit of this test: it ran in a Linux container, not on the M-series Macs we build on, and the app is small. The ratio and the error list are what we were after, and both held up in the three configurations we tried. We will add Mac numbers from a client app once the first one moves.
The benchmark script
#!/usr/bin/env python3
import resource, subprocess, statistics, sys, time
N = int(sys.argv[1]) if len(sys.argv) > 1 else 5
CMDS = {
"tsc 6.0.3": ["node", "node_modules/typescript/bin/tsc", "--noEmit", "-p", "tsconfig.json"],
"tsc 7.0.2": ["node_modules/ts7/bin/tsc", "--noEmit", "-p", "tsconfig.json"],
"tsc 7.0.2 --singleThreaded": ["node_modules/ts7/bin/tsc", "--noEmit", "-p", "tsconfig.json", "--singleThreaded"],
}
times = {k: [] for k in CMDS}
for _ in range(N):
for name, cmd in CMDS.items():
t0 = time.perf_counter()
subprocess.run(cmd, capture_output=True)
times[name].append(time.perf_counter() - t0)
for name, cmd in CMDS.items():
out = subprocess.run([sys.executable, "-c",
"import resource,subprocess,sys; subprocess.run(sys.argv[1:],capture_output=True); "
"print(resource.getrusage(resource.RUSAGE_CHILDREN).ru_maxrss)", *cmd],
capture_output=True, text=True)
t = times[name]
print(f"{name:28s} median {statistics.median(t):.2f}s min {min(t):.2f}s max {max(t):.2f}s peak {int(out.stdout)//1024} MB")
Sources: Microsoft’s TypeScript 7.0 announcement (8 July 2026) for the defaults, removed options and the side-by-side package; the React Native 0.87 release post (11 Aug 2026) for the strict TypeScript API; and the typescript-eslint tracking issue linked in its own error message.



