如何在 React Navigation 中正确输入 useNavigation?
How to properly type useNavigation in React Navigation?
我正在尝试从 React Navigation 中输入 useNavigation
。我希望能够只传递路线的名称,但我得到一个错误,除非我也为该路线传递道具。
在 the documentation 之后,我理解实现应该如下所示:
import { StackNavigationProp } from '@react-navigation/stack';
type StackParamList = {
Home: { foo: string, onBar: () => void }
About: AboutProps
}
type NavigationProps = StackNavigationProp<StackParamList>
const MyComponent = () => {
const navigation = useNavigation<NavigationProps>()
const handleOnNavigate = () => navigation.navigate('Home')
// ^ TypeError!
我在最后一行收到 TypeError。如果我为该路线添加道具,错误就会消失,但我不必那样做。
navigation.navigate('Home', { foo: 'hello', onBar: () => {} })
查看 navigation.navigate
的类型声明(见下文),这应该不是必需的,因为有一个重载可以简单地将路由名称作为唯一参数传递。我一定是做错了什么,因为那是不被接受的……但是什么,在哪里,为什么?
Here is a CodeSandBox reproducing the TypeError.
React 导航types.d.ts (link)
navigate<RouteName extends keyof ParamList>(...args: undefined extends ParamList[RouteName]
? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
: [screen: RouteName, params: ParamList[RouteName]])
: void;
I am geting a TypeError on the last line there. If I add the props for that route, the error disappears, but I shouldn't have to do that.
您指定的类型为:
Home: { foo: string, onBar: () => void }
这意味着 Home
采用这些参数。如果你的路线不带任何参数,你可以做 navigate('Home')
,你不应该在类型中指定任何参数。
如果这些参数是可选的,那么您需要相应地指定类型:
Home: { foo: string, onBar: () => void } | undefined
在您的类型 StackParamList
中,您可以定义导航到屏幕时期望的参数类型。如果您不希望 Home 有任何参数,您还必须相应地在您的类型中定义它:
export type StackParamList = {
Home: undefined,
About: { bar: string; onBaz: () => void };
};
如果您希望任何附加参数可选,您可以在类型声明中使用管道:
export type StackParamList = {
Home: { foo: string; onBar: () => void } | undefined;
About: { bar: string; onBaz: () => void };
};
// Will work in both ways:
const handleOnNavigate = () => navigation.navigate('Home')
作为解决方法,您还可以使用另一个重载并传递一个配置对象:
const handleOnNavigate = () => navigation.navigate({key : "Home"});
为了使其仅使用一个参数,您需要添加 | undefined
.
让我解释一下为什么你需要这样做。
考虑这个声明:
navigate<RouteName extends keyof ParamList>(
...args: undefined extends ParamList[RouteName]
? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
: [screen: RouteName, params: ParamList[RouteName]]
): void;
这是最有趣的部分:undefined extends ParamList[RouteName]
这意味着如果 undefined
extends ParamList[RouteName]
你只能使用一个参数。
让我们把它分成更小的例子:
type ParamList = {
Home: { foo: string; onBar: () => void };
About: { bar: string; onBaz: () => void };
Undefined: undefined,
};
type Check<T extends keyof ParamList> = undefined extends ParamList[T] ? 'might be undefined' : 'can not be undefined'
type Result = Check<'Home'> // "can not be undefined"
type Result2 = Check<'Undefined'> // "might be undefined"
您可能已经注意到,如果您提供 Home
TS 将需要两个参数,因为 ParamList['Home']
returns 一个对象不能是 undefined
.
另一方面,undefined
扩展了 ParamList['Undefined']
- 因此 TS 只允许您使用一个参数。
这就是为什么 TS 不允许你只传递一个参数。
我正在尝试从 React Navigation 中输入 useNavigation
。我希望能够只传递路线的名称,但我得到一个错误,除非我也为该路线传递道具。
在 the documentation 之后,我理解实现应该如下所示:
import { StackNavigationProp } from '@react-navigation/stack';
type StackParamList = {
Home: { foo: string, onBar: () => void }
About: AboutProps
}
type NavigationProps = StackNavigationProp<StackParamList>
const MyComponent = () => {
const navigation = useNavigation<NavigationProps>()
const handleOnNavigate = () => navigation.navigate('Home')
// ^ TypeError!
我在最后一行收到 TypeError。如果我为该路线添加道具,错误就会消失,但我不必那样做。
navigation.navigate('Home', { foo: 'hello', onBar: () => {} })
查看 navigation.navigate
的类型声明(见下文),这应该不是必需的,因为有一个重载可以简单地将路由名称作为唯一参数传递。我一定是做错了什么,因为那是不被接受的……但是什么,在哪里,为什么?
Here is a CodeSandBox reproducing the TypeError.
React 导航types.d.ts (link)
navigate<RouteName extends keyof ParamList>(...args: undefined extends ParamList[RouteName]
? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
: [screen: RouteName, params: ParamList[RouteName]])
: void;
I am geting a TypeError on the last line there. If I add the props for that route, the error disappears, but I shouldn't have to do that.
您指定的类型为:
Home: { foo: string, onBar: () => void }
这意味着 Home
采用这些参数。如果你的路线不带任何参数,你可以做 navigate('Home')
,你不应该在类型中指定任何参数。
如果这些参数是可选的,那么您需要相应地指定类型:
Home: { foo: string, onBar: () => void } | undefined
在您的类型 StackParamList
中,您可以定义导航到屏幕时期望的参数类型。如果您不希望 Home 有任何参数,您还必须相应地在您的类型中定义它:
export type StackParamList = {
Home: undefined,
About: { bar: string; onBaz: () => void };
};
如果您希望任何附加参数可选,您可以在类型声明中使用管道:
export type StackParamList = {
Home: { foo: string; onBar: () => void } | undefined;
About: { bar: string; onBaz: () => void };
};
// Will work in both ways:
const handleOnNavigate = () => navigation.navigate('Home')
作为解决方法,您还可以使用另一个重载并传递一个配置对象:
const handleOnNavigate = () => navigation.navigate({key : "Home"});
为了使其仅使用一个参数,您需要添加 | undefined
.
让我解释一下为什么你需要这样做。
考虑这个声明:
navigate<RouteName extends keyof ParamList>(
...args: undefined extends ParamList[RouteName]
? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
: [screen: RouteName, params: ParamList[RouteName]]
): void;
这是最有趣的部分:undefined extends ParamList[RouteName]
这意味着如果 undefined
extends ParamList[RouteName]
你只能使用一个参数。
让我们把它分成更小的例子:
type ParamList = {
Home: { foo: string; onBar: () => void };
About: { bar: string; onBaz: () => void };
Undefined: undefined,
};
type Check<T extends keyof ParamList> = undefined extends ParamList[T] ? 'might be undefined' : 'can not be undefined'
type Result = Check<'Home'> // "can not be undefined"
type Result2 = Check<'Undefined'> // "might be undefined"
您可能已经注意到,如果您提供 Home
TS 将需要两个参数,因为 ParamList['Home']
returns 一个对象不能是 undefined
.
另一方面,undefined
扩展了 ParamList['Undefined']
- 因此 TS 只允许您使用一个参数。
这就是为什么 TS 不允许你只传递一个参数。