React Native never type-checks your TypeScript when it builds. Metro hands every file to Babel, Babel deletes the type annotations, and the bundle ships. A function that expects a number and gets a string bundles without a single warning. You find out at runtime, usually on a screen you didn't open while testing.

The editor underlines the error in red, so it's easy to assume the build checks it too. It doesn't. Only tsc does, and nothing runs tsc unless you tell it to.

I made type errors fail the build. It takes two pieces.

The npm script

In package.json:

{ "scripts": { "typecheck": "tsc --noEmit", "android": "npm run typecheck && react-native run-android" } } 

--noEmit is the important flag. Metro already produces the JavaScript, so tsc only has to check.

The Gradle hook

The script covers anyone who starts the app with npm run android. It does nothing when someone presses Run in Android Studio, or when CI calls ./gradlew assembleRelease directly. So I hooked the same check into Gradle, in android/app/build.gradle:

def isWindows = System.getProperty('os.name').toLowerCase().contains('windows') tasks.register('typecheck', Exec) { workingDir = rootProject.projectDir.parentFile commandLine isWindows ? ['cmd', '/c', 'npx', 'tsc', '--noEmit'] : ['npx', 'tsc', '--noEmit'] } preBuild.dependsOn 'typecheck' 

The Windows branch exists because Gradle's Exec can't launch npx directly there. On Windows npx is a .cmd shim, so it has to go through cmd /c.

When tsc finds an error it exits non-zero, the Exec task fails, and Gradle stops before it compiles anything.

This puts a full type-check in front of every Android build, so on a large codebase you'll feel it. If that gets annoying during development, keep the npm script for local runs and attach the Gradle task only to release builds.