First, I show my type-definitions.
// Define screens. The key is a screen name. The value is a parameter passed to a navigation object.
export type Screens = {
}
// Define your navigators.
export type Navigators = {
}
type Navigatable<T> = T extends keyof Screens
? ScreenParams<T>
: T extends keyof Navigators
? NavigatorParams<T>
: never
type ScreenParams<T extends keyof Screens> = {
screen: T
params: Screens[T]
}
type NavigatorParams<T extends keyof Navigators> = {
screen: T
params: Navigators[T]
}
export type NavigationParams = Screens & Navigators
export type TypedNavigatorParams<T extends keyof Navigators> = Pick<
NavigationParams,
NavigationParams[T]['screen']
>
Usage
Read my repository for detail.
https://github.com/ryohlan/typesafe-react-navigation-sample
if you are considering the following structure:
AppNavigator
- AuthNavigator
- launch
- signup
- MainNavigator
- MainTabNavigator
- home
- search
You can define the Screens and the Navigators the following:
// Define screens. The key is a screen name. The value is a parameter passed to a navigation object.
export type Screens = {
launch: {}
signup: { signupParam: string }
home: {}
search: { searchParam: number }
}
// Define your navigators.
export type Navigators = {
AppNavigator: Navigatable<'AuthNavigator' | 'MainNavigator'>
AuthNavigator: Navigatable<'launch'|'signup'>
MainNavigator: Navigatable<'MainTabNavigator'>
MainTabNavigator: Navigatable<'home'|'search>
}
A Navigator also can be checked:
import React from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import { TypedNavigatorParams } from './NavigationParams'
import { LaunchScreen } from '../screens/LaunchScreen'
const { Screen, Navigator } = createStackNavigator<TypedNavigatorParams<'AuthNavigator'>>()
export const AuthNavigator = () => {
return (
<Navigator mode="card">
<Screen {...LaunchScreen} />
</Navigator>
)
}
And create custom hooks for navigation.
import { useNavigation as useDefaultNavigation } from '@react-navigation/core'
import { StackNavigationProp } from '@react-navigation/stack'
import { NavigationParams } from '@src/components/navigators/NavigationParams'
export const useNavigation = () => useDefaultNavigation<StackNavigationProp<NavigationParams>>()
You can navigate type-safely using useNavigation!
const navigation = useNavigation()
navigation.navigate('AppNavigator', {
screen: 'AuthNavigator',
params: {
screen: 'signup',
params: { signupParam: '' }, // If
},
})
Top comments (0)