Typescript:部分键入一个react-navigation spy helper



(这与三年前的帖子有些关系。我试着按照答案去做,但他们没有解决我的问题。

我想建立一个通用的模拟(间谍)导航器,我可以像这里一样传入spyNavigation:

it('shows an error if the request fails', async () => {
const spyNavigation = {
replace: jest.fn(),
push: jest.fn(),
}
mockServer.use(
rest.get('*/users/current-user', (req, res, ctx) => {
return res(ctx.status(200), ctx.json({ id: 1 }))
})
)
mockServer.use(
rest.get('*/some-data', (req, res, ctx) => {
return res(ctx.status(500))
})
)
// @ts-ignore
TestHelper.renderWithReactQueryClient(<OverviewScreen navigation={spyNavigation} />)
await TestHelper.waitForWithExtendedTimeOut(() => {
expect(spyNavigation.push).toHaveBeenCalledWith('Error', {
error: new Error('Request failed with status code 500'),
})
})
})

我想将spyNavigation抽象为测试助手,并让TypeScript帮助我部分键入它。因此,它将代码完成方法,如'replace', 'push'等。

react-navigation的TypeScript太复杂了,我无法理解。如果间谍不知道屏幕/导航器的名字,那就好了——只是一个一般的"导航"。对象。

import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native'
import { NativeStackScreenProps } from '@react-navigation/native-stack'
import { AxiosError } from 'axios'
declare global {
namespace ReactNavigation {
interface RootParamList extends RootStackParamList {}
}
}
export type RootStackParamList = {
SignInOrCreateUser: undefined
SignIn: undefined
Root: NavigatorScreenParams<RootTabParamList> | undefined
Modal: undefined
Error: { error: AxiosError | null } | undefined
}
export type RootTabParamList = {
Overview: undefined
Returns: undefined
Portfolio: undefined
More: undefined
}
export type RouteName = keyof RootStackParamList | keyof RootTabParamList
export const routeTypeGuard = (route: RouteName) => route
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = NativeStackScreenProps<
RootStackParamList,
Screen
>
export type RootTabScreenProps<Screen extends keyof RootTabParamList> = CompositeScreenProps<
BottomTabScreenProps<RootTabParamList, Screen>,
NativeStackScreenProps<RootStackParamList>
>

这行不通

import { NativeStackNavigatorProps } from '@react-navigation/native-stack/lib/typescript/src/types'
export const mockNavigation: NativeStackNavigatorProps = {
navigate: jest.fn(),
push: jest.fn(),
replace: jest.fn(),
pop: jest.fn(),
}
Type '{ navigate: jest.Mock<any, any>; push: jest.Mock<any, any>; replace: jest.Mock<any, any>; pop: jest.Mock<any, any>; }' is not assignable to type 'NativeStackNavigatorProps'.
Object literal may only specify known properties, and 'navigate' does not exist in type 'NativeStackNavigatorProps'.ts(2322)

我猜应该是

export const mockNavigation: Record<keyof ???, () => ReturnType<typeof jest.fn>> = {
navigate: jest.fn(),
push: jest.fn(),
replace: jest.fn(),
pop: jest.fn(),
}

下面是您评论后的问题的潜在解决方案!我希望这对你有用。我正在扩展StackNavigationProp,它具有您想要的功能名称:navigate,push等。同样从你的问题中,我将其属性的类型替换为jest.fn的返回。

MockStackNavigationProp的可选泛型也应该反映StackNavigationProp的泛型,允许您指定ParamList是否可用。

如果这有效,我想知道是否可以进一步使jest函数模拟的参数类型也从原始函数定义中自动推断出来。

import { ParamListBase } from "@react-navigation/native";
import { StackNavigationProp } from "@react-navigation/stack";
type MockStackNavigationProp<
ParamList extends ParamListBase = any,
RouteName extends keyof ParamList = string
> = Record<
keyof StackNavigationProp<ParamList, RouteName>,
ReturnType<typeof jest.fn>
>;
const mockNavigation: MockStackNavigationProp = {
navigate: jest.fn(),
pop: jest.fn(),
push: jest.fn()
//.. and more, OR use Partial<MockStackNavigationProp>
};

CodeSandbox链接。

相关内容

最新更新