在Typescript中,当存储然后从数组访问该对象时,如何维护对象类型?

时间:2019-05-17 14:43:03

标签: javascript arrays typescript puppeteer

在打字稿中,我注意到当我将一个复杂的对象放入数组中时,当我尝试从数组访问该对象时,它会丢失其类型,而只是变成对象类型。

例如

let myArray = return await this.browser.evaluate((sel: string) => Array.from(document.querySelectorAll(sel)), selector)

document.querySelectorAll(sel)返回NodeList<Element>的{​​{1}}。 ArrayLike应该将Array.from转换为元素数组,但是一旦形成数组,所有的数组元素都会失去其NodeList类型

我有一个仅接受类型为Element的参数的函数,但是当我尝试将Element作为所述函数的参数传递时,出现错误:myArray[0] < / p>

我已经尝试了很多不同的方法来尝试使数组保持其对象类型,以致难以解释每一个对象。我想知道如何创建Error: Unsupported target type: object数组,并在以后访问它们而不是通用Element时继续使它们成为Element

在我完成的测试中,这里还有更多内容

我要转到此页面:https://www.w3schools.com/html/html_tables.asp 而我要传递给评估的选择器是object,应该与表中出现的6行匹配。

table[id="customers"] tbody tr

运行上面的代码时,这是我在控制台日志中得到的输出:

let test = await this.browser.evaluate((sel: string) => 
Array.from(document.querySelectorAll(sel)), selector)
console.log('testy1: ', test)
console.log('testy2: ', test[0])
console.log('testy3: ', typeof(test[0]))

似乎正确地从页面中获取了元素,因为它正确地返回了6个元素。但也许问题在于返回的对象为空?我不确定。

我认为我的问题可能与以下问题有关:puppeteer page.evaluate querySelectorAll return empty objects

但是该问题的解决方案对我不起作用,因为href不是对象类型testy1: [ {}, {}, {}, {}, {}, {}, {} ] testy2: {} testy3: object 的属性

2 个答案:

答案 0 :(得分:1)

这里的问题是要传递给page.evaluate的函数在浏览器上下文内(在浏览器页面内)运行。要将结果从浏览器上下文发送到Node.js环境,需要对结果进行序列化。

在文档中查看page.evaluate的返回类型:

  

returns:Promise <Serializable> Promise可解析为pageFunction的返回值

这里的Serializable意味着您的数据将通过JSON.stringify传递到Node.js环境,并在那里自动为您解析。但是,此过程将删除对象的所有不可序列化的属性。这就是为什么最终会有许多空对象的原因。

在操纵up中获取元素句柄

要获取页面上元素的句柄,您需要使用page.$,它会创建一个对象(在Node.js环境中),该对象链接到浏览器上下文中的元素。这些句柄也可以传递给page.evaluate调用。要查询多个元素,可以使用函数page.$$

代码示例

这里是一个示例,该示例首先查询元素,然后将元素句柄传递给评估函数以读取属性。

const elementHandle = await page.$('a');
const result = await page.evaluate(el => el.href, elementHandle);

TypeScript的用法

与TypeScript有关的问题是,在这种情况下TypeScript无法正确预测类型。对于TypeScript编译器,这看起来像一个普通的函数调用,而实际上,该函数将发送到客户端以执行。因此,在这种情况下,您必须自己转换类型,否则Typescript只会假设any作为参数类型:

const elementHandle = await page.$('a');
const result = await page.evaluate((el: { href: string }) => el.href, elementHandle);

答案 1 :(得分:0)

我在类型定义上遇到了同样的问题,并且Element没有从任何Lib中导出。

要使用el方法获得适当的智能,我用以下示例更改了代码:

发件人:

...  
await page.waitForTimeout(3000)
await page.waitForSelector('button[type=submit]') 
await page.$eval('button[type=submit]', el => el.click())
await page.waitForNavigation({waitUntil: "load"})
await page.goto(url)
...

对此:

...  
await page.waitForTimeout(3000) 
await page.waitForSelector('button[type=submit]')
await page.$('button[type=submit]').then(el => {
  el.click()
})
await page.waitForNavigation({waitUntil: "load"})
await page.goto(url)
...

puppeteer element intelisense example

PS:我在DefinedType Github https://github.com/DefinitelyTyped/DefinitelyTyped/issues/24419

的定义类型中发现了问题