React Native导航:动态生成页面时navigation.navigate类型报错问题
React Native + TypeScript:动态路由导航的ts(2769)类型错误解决
我在React Native中使用Animated.ScrollView动态生成带导航功能的Page组件,定义了包含Home、ReactQuiz等路由的RootStackParamList,通过遍历routes数组给Page组件传递路由信息,在Page组件的按钮点击事件中调用navigation.navigate(item.route)实现跳转,但触发了TypeScript的ts(2769)类型错误——提示string类型无法匹配RootStackParamList中定义的具体路由名称类型。
相关代码
ScrollView组件
type Props = NativeStackScreenProps<RootStackParamList, "Practice">; const ScrollView = ({ navigation, route }: Props) => { const translateX = useSharedValue(0); const scrollHandler = useAnimatedScrollHandler((event) => { translateX.value = event.contentOffset.x; }); return ( <> <Animated.ScrollView onScroll={scrollHandler} scrollEventThrottle={16} horizontal style={styles.scrollContainer} > {routes.map((item, index) => { return ( <Page key={item.route} item={item} index={index} translateX={translateX} navigation={navigation} route={route} /> ); })} </Animated.ScrollView> </> ); };
RootStackParamList定义
export type RootStackParamList = { Home: undefined; ReactQuiz: undefined; LinuxQuiz: undefined; Practice: undefined; MongoDBQuiz: undefined; };
routes数组
const routes = [ { route: "LinuxQuiz", bgColor: "black", fontColor: "yellow", }, { route: "ReactQuiz", bgColor: "#88dded", fontColor: "#1c2c4c", }, { route: "MongoDBQuiz", bgColor: "#3FA037", fontColor: "#4DB33D", }, ];
Page组件
interface PageProps extends NativeStackScreenProps<RootStackParamList, "Practice"> { item: { route: string; bgColor: string; fontColor: string; }; index: number; translateX: Animated.SharedValue<number>; } const Page: React.FC<PageProps> = ({ item, index, translateX, navigation, route }) => { return ( <View> <RectangleButton onPress={() => navigation.navigate(item.route)} > {item.route} </RectangleButton> </View> ); }; export default Page;
错误信息
No overload matches this call. Argument of type '[string]' is not assignable to parameter of type '[screen: "Practice"] | [screen: "Practice", params: undefined] | [screen: "Home"] | [screen: "Home", params: undefined] | [screen: "ReactQuiz"] | [screen: "ReactQuiz", params: undefined] | [screen: "LinuxQuiz"] | [screen: "LinuxQuiz", params: undefined] | [screen: "MongoDBQuiz"] | [screen: ...]'. Overload 2 of 2, '(options: { key: string; params?: undefined; merge?: boolean | undefined; } | { name: "Practice"; key?: string | undefined; params: undefined; merge?: boolean | undefined; } | { key: string; params?: undefined; merge?: boolean | undefined; } | ... 6 more ... | { ...; }): void', gave the following error. Argument of type 'string' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: "Practice"; key?: string | undefined; params: undefined; merge?: boolean | undefined; } | { key: string; params?: undefined; merge?: boolean | undefined; } | ... 6 more ... | { ...; }'.ts(2769) No overload matches this call. Argument of type '[string]' is not assignable to parameter of type '[screen: "Practice"] | [screen: "Practice", params: undefined] | [screen: "Home"] | [screen: "Home", params: undefined] | [screen: "ReactQuiz"] | [screen: "ReactQuiz", params: undefined] | [screen: "LinuxQuiz"] | [screen: "LinuxQuiz", params: undefined] | [screen: "MongoDBQuiz"] | [screen: ...]'. Type '[string]' is not assignable to type '[screen: "Practice"] | [screen: "Home"] | [screen: "ReactQuiz"] | [screen: "LinuxQuiz"] | [screen: "MongoDBQuiz"]'. Type '[string]' is not assignable to type '[screen: "MongoDBQuiz"]'. Type 'string' is not assignable to type '"MongoDBQuiz"'. Overload 2 of 2, '(options: { key: string; params?: undefined; merge?: boolean | undefined; } | { name: "Practice"; key?: string | undefined; params: undefined; merge?: boolean | undefined; } | { key: string; params?: undefined; merge?: boolean | undefined; } | ... 6 more ... | { ...; }): void', gave the following error. Argument of type 'string' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: "Practice"; key?: string | undefined; params: undefined; merge?: boolean | undefined; } | { key: string; params?: undefined; merge?: boolean | undefined; } | ... 6 more ... | { ...; }'.ts(2769)
解决方案
问题核心是TypeScript无法识别item.route的具体类型,仅将其视为宽泛的string类型。我们需要给routes数组和Page组件的props添加精确的类型约束:
方法一:提取路由名称联合类型
- 从
RootStackParamList中导出路由名称的联合类型:
export type RootStackRouteNames = keyof RootStackParamList;
- 给
routes数组指定类型:
const routes: Array<{ route: RootStackRouteNames; bgColor: string; fontColor: string; }> = [ { route: "LinuxQuiz", bgColor: "black", fontColor: "yellow", }, { route: "ReactQuiz", bgColor: "#88dded", fontColor: "#1c2c4c", }, { route: "MongoDBQuiz", bgColor: "#3FA037", fontColor: "#4DB33D", }, ];
- 修改Page组件的
PageProps类型:
interface PageProps extends NativeStackScreenProps<RootStackParamList, "Practice"> { item: { route: RootStackRouteNames; bgColor: string; fontColor: string; }; index: number; translateX: Animated.SharedValue<number>; }
方法二:使用as const自动推断精确类型
- 给
routes数组添加as const断言,让TypeScript自动推断每个route的字面量类型:
const routes = [ { route: "LinuxQuiz", bgColor: "black", fontColor: "yellow", }, { route: "ReactQuiz", bgColor: "#88dded", fontColor: "#1c2c4c", }, { route: "MongoDBQuiz", bgColor: "#3FA037", fontColor: "#4DB33D", }, ] as const;
- 修改Page组件的
PageProps类型,直接复用routes的元素类型:
interface PageProps extends NativeStackScreenProps<RootStackParamList, "Practice"> { item: typeof routes[number]; index: number; translateX: Animated.SharedValue<number>; }
两种方法都能让TypeScript确认item.route是RootStackParamList中定义的具体路由名称,而非宽泛的string类型,从而解决ts(2769)类型错误。
内容的提问来源于stack exchange,提问作者Mathew
相关产品推荐
相关产品推荐

