我的React Native应用程序的Typescript和React Navigation存在问题。我在项目中设置了以下设置,在使用以下示例时,它为我提供了很棒的帮助和自动完成功能navigation.push()
。
类型
import { StackNavigationProp } from '@react-navigation/stack';
export type RootStackParamList = {
Home: undefined;
Content: undefined;
List: undefined;
};
export type StackNavigationProps = StackNavigationProp<RootStackParamList>;
用法
const navigation = useNavigation<StackNavigationProps>();
但是,我创建了一个导航处理程序函数,该函数带有一个被馈送到navigation.push
的参数。只要参数的类型为any
,它就可以正常工作。
const navigationHandler = useCallback((targetScreen) => {
navigation.push(targetScreen);
}, [navigation]);
但是我对any
类型不满意,希望targetScreen
实际上只是我的RootStackParamList
类型中声明的屏幕之一。我已经尝试了无数种方法来满足导航对象的push
方法,但是我遇到了麻烦。
以下尝试是最成功的尝试,但仍未达到应有的效果。它确实可以在可用屏幕上为我自动补全,但是push
仍然不满意。
类型:
export type NavigationScreen<T extends RootStackParamList> = {
[K in keyof T]: K;
}[keyof T];
用法:
const navigationHandler = useCallback(
<T extends RootStackParamList>(targetScreen: NavigationScreen<T>) => {
navigation.push(targetScreen);
},[navigation]);
悬停错误,提示我以下内容:
(参数)targetScreen:{[T键中的K]:K; } [keyof T]的论点输入'[{[T键中的K]:K; } [keyof T]]'无法分配给'[“ Home”类型的参数| “内容” | “列表”] | [“首页” | “内容”| “列表”,未定义]”。输入'[{[T键中的K]:K; } [keyof T]]'是不可分配给类型'[“ Home” | “内容” | “列表”]'。类型'keyof T'不能分配给类型'“ Home” | “内容” | “列表”。输入'string |编号符号'不能分配给类型'“ Home” | “内容” | “列表”。类型'string'不能分配给类型'“ Home” | “内容” | “列表”。类型“ keyof T”不可分配给类型““ List””。输入'string |编号符号”不可分配给“列表”类型。类型'string'不可分配给类型'“ List”'。
如何使它工作?
[如果您只想将屏幕名称用于navigationHandler
函数,而不是参数,则可以按照@artcorpse在他对问题的注释中建议的方式进行操作,并使用keyof RootStackParamList
:
const navigationHandler = useCallback(
(targetScreen: keyof RootStackParamList) => {
navigation.push(targetScreen);
},
[navigation]
);
另一方面,如果您想允许参数,则有两个选择:
const navigationHandler = useCallback(
<T extends keyof RootStackParamList>(
targetScreen: T,
targetScreenParams?: RootStackParamList[T]
) => {
navigation.push(
targetScreen as keyof RootStackParamList,
targetScreenParams
);
},
[navigation]
);
此选项的好处是,根据RootStackParamList
类型中定义的相应路线检查路线参数对象的形状。例如,
type RootStackParamList = {
Default: undefined,
Home: {a: 'a'};
Profile: { userId: string };
};
navigationHandler('Home', {a: 'a'}); //OK
navigationHandler('Home', {userId: 'a'}); //ERROR
const navigationHandler2 = useCallback(
(
targetScreen: Parameters<typeof navigation.push>[0],
targetScreenParams?: Parameters<typeof navigation.push>[1]
) => {
navigation.push(targetScreen, targetScreenParams);
},
[navigation]
);
此选项采用您已定义的现有类型,并尝试从navigation.push
方法中提取它们。不利之处在于,您不会获得上述有关路径及其相应参数对象形状的检查。