Minimal reproduction showing that expo-router@55.0.3 types are incompatible with TypeScript's exactOptionalPropertyTypes.
Open in StackBlitz (run npx tsc --noEmit in the terminal)
Or locally:
git clone https://github.com/YevheniiKotyrlo/str-expo-router-eopt.git
cd str-expo-router-eopt
npm install
npx tsc --noEmitExpected: 0 errors
Actual: 3 errors (TS2375, TS2345) in consumer code — even with skipLibCheck: true
repro.tsx(19,7): error TS2375: Type '{ name: string; options: ... | undefined; }' is not assignable
to type 'ScreenProps' with 'exactOptionalPropertyTypes: true'.
repro.tsx(32,3): error TS2375: Type '{ name: string; redirect: undefined; ... }' is not assignable
to type 'Partial<ScreenProps>' with 'exactOptionalPropertyTypes: true'.
repro.tsx(48,15): error TS2345: Argument of type '{ pathname: string; params: undefined; }' is not
assignable to parameter of type 'string | HrefObject'.
npx tsc --noEmit --skipLibCheck false144 errors across expo-router, @react-navigation, and react-native .d.ts files.
npx tsc --noEmit --exactOptionalPropertyTypes false0 errors — confirms exactOptionalPropertyTypes is the sole cause.
With exactOptionalPropertyTypes, prop?: T means "if present, must be exactly T" — explicitly passing undefined is a type error. The fix is prop?: T | undefined.
expo-router's exported types (ScreenProps, HrefObject, etc.) define optional properties as prop?: T without | undefined. Consumer code that assigns undefined to these properties — a common pattern for conditional options — gets type errors.
skipLibCheck: true doesn't help because the errors are in the consumer's .tsx files, not in .d.ts files. TypeScript still loads and enforces the types from .d.ts declarations.
- TypeScript 5.9's
tsc --initenablesexactOptionalPropertyPropertiesby default - Libraries commonly used with Expo have already shipped support: Zustand, TanStack Query, Zod v4, Storybook
- react-navigation has PRs in review adding the same support
Add | undefined to optional properties in expo-router's type definitions. This is backwards-compatible: prop?: T and prop?: T | undefined are identical when exactOptionalPropertyTypes is disabled.
See expo/expo#43506.
- expo: 55.0.3
- expo-router: 55.0.3
- react-native: 0.83.2
- react: 19.2.0
- typescript: 5.9.3
- expo-doctor: 17/17 checks passed