如何从TypeScript模块导出返回Playwright `expect`对象的函数?
expect对象的函数? 我之前也碰到过一模一样的问题——Playwright把PollMatchers、GenericAssertions这些和断言相关的内部类型藏得死死的,完全不对外导出,导致封装公共函数时TypeScript报错,还不能直接写返回类型,确实挺闹心的。
下面给你几个实用的解决方案,既能保留类型提示,又能顺利导出函数:
方案一:用ReturnType自动提取返回类型(推荐)
既然我们不能直接引用内部的PollMatchers,那就让TypeScript自己帮我们“捕获”这个类型。利用TypeScript的ReturnType工具类型,我们可以从expect.poll的实际调用结果中提取出准确的返回类型,不用手动写那些未导出的类型名:
import { Expect } from '@playwright/test'; import { LinkablePage } from './your-page-objects'; // 辅助类型:自动提取expect.poll的返回类型 type PollMatcherReturn<TExpect, TPoll> = ReturnType<Expect<TExpect>['poll']<TPoll>>; export function reloadAndPoll<TExpect, TPoll>( expecter: Expect<TExpect>, page: LinkablePage, pollFunction: () => Promise<TPoll>, testBeforeReload = true ): PollMatcherReturn<TExpect, TPoll> { let n = 0; // 这里的类型断言是可选的,有时候TypeScript能自动推导,但加上更保险 return expecter.poll(async () => { if (!testBeforeReload || n++ > 0) await page.reload(); return pollFunction(); }) as PollMatcherReturn<TExpect, TPoll>; }
这个方案的好处是完全保留了expect.poll返回值的所有类型信息,调用方用起来和直接用Playwright原生的poll完全一样,类型提示一点都不会少。
方案二:用已导出的Matchers类型做折中
如果方案一偶尔有类型推导的小问题,还可以用Playwright对外导出的Matchers类型来做返回类型的近似。虽然会丢失一些poll特有的方法,但大部分常用的断言(比如toBe、toEqual这些)都能正常保留:
import { Expect, Matchers } from '@playwright/test'; import { LinkablePage } from './your-page-objects'; export function reloadAndPoll<TExpect, TPoll>( expecter: Expect<TExpect>, page: LinkablePage, pollFunction: () => Promise<TPoll>, testBeforeReload = true ): Matchers<Promise<TPoll>, TPoll> { let n = 0; return expecter.poll(async () => { if (!testBeforeReload || n++ > 0) await page.reload(); return pollFunction(); }) as unknown as Matchers<Promise<TPoll>, TPoll>; }
这里用as unknown as做类型转换是为了绕过TypeScript的类型检查,因为内部类型和导出的Matchers是兼容的,但TypeScript自己不知道。
方案三:给Playwright提Feature Request
如果你们团队长期需要封装这类和断言相关的公共函数,还可以去Playwright的GitHub仓库提一个Feature Request,要求他们把PollMatchers以及依赖的内部断言类型对外导出。毕竟很多团队都会有封装公共测试工具的需求,官方说不定会采纳这个建议。
内容来源于stack exchange

