網站搜尋

puppeteer - 帶有回調函數和參數的 Typescript 泛型類型(封裝 puppeteer)


我正在嘗試為 Puppeteer 做一些封裝函數。但我在處理 TypeScript 的類型時遇到了困難。

基本上,Puppeteer 允許以這種方式注入一些程式碼

page.$eval("selector" ,(element, args) => {}, someArgs)

我想做一個函數,它允許使用回調並傳遞 "someArgs"。我的選擇器保持不變。

這是我的嘗試(下面也附有 stackBlitz 連結以獲得詳細重現)

import puppeteer from 'puppeteer';

(async () => {
  const browser = await puppeteer.launch({});
  const page = await browser.newPage();

  const runForVideo = <T extends any[]>(
    cb: (video: HTMLVideoElement, ...args: [...T, ...undefined[]]) => void,
    ...args: T
  ) => page.$eval('video', (video, ...args) => cb(video, ...args), args); // ...args are yielding :'(
  // Argument of type '[FlattenHandle<T>]' is not assignable to parameter of type '[...T, ...undefined[]]'.
  // Source provides no match for variadic element at position 0 in target.(2345)

  await runForVideo((video, a) => {
    // a is undefined
  });
  await runForVideo((video, volume) => {
    video.volume = volume;
  }, 5);
  await runForVideo(
    (video, volume, text) => {
      video.volume = volume;
      console.log(text);
    },
    5,
    'hello'
  );
})();

我希望那個 runForVideo 的第一個參數回調只有在 runForVideo 有一個(或多個)參數時才有第二個參數,並且類型相同。

有沒有什麼想法可以繼續進行?

謝謝

附註:我在這裡添加了一個完整的範例:https://stackblitz.com/edit/node-zxyvaa?file=index.ts,你可以看到這個方法工作正常,只是 cb 生成的是它需要的 FlattenHandle

答案#1

你得到的錯誤是你的回呼類型與 puppetter 的回呼類型不相容。puppeteer 期望一個與 string | EvaluateFuncWith<Element,V> 相容的類型。如果你將你的函數簽名改成這個:

  const runForVideo = <T extends any[]>(
    cb: EvaluateFuncWith<HTMLVideoElement, [...T]>,
    ...args: T
  ) => page.$eval('video', cb, ...args); 

它應該會如預期般運作。

Stackblitz