繁体   English   中英

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

[英]In Typescript, how do I maintain an objects type when storing and then accessing said object from an array?

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

例如

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

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

我有一个只接受Element类型参数的函数,但是当我尝试将myArray[0]作为参数传递给所述函数时,出现错误: Error: Unsupported target type: object

我尝试了很多不同的方法来尝试让数组保持其对象类型,因此很难解释其中的每一个。 我想知道如何创建一个Element数组并让它们在以后访问时继续是Element而不是通用object

这是我所做的测试中的更多背景信息

我要去这个页面: https : //www.w3schools.com/html/html_tables.asp和我传递给评估的选择器是table[id="customers"] tbody tr这应该与出现的 6 行匹配在表中。

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]))

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

testy1:  [ {}, {}, {}, {}, {}, {}, {} ]
testy2:  {}
testy3:  object

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

我想我的问题可能与这个问题有关: puppeteer page.evaluate querySelectorAll return empty objects

但该问题的解决方案对我不起作用,因为 href 不是对象类型Element的属性

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

请参阅page.evaluate文档中的返回类型:

返回: Promise< Serializable > Promise,它解析为pageFunction的返回值

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

在 puppeteer 中获取元素句柄

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

代码示例

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

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

打字稿的使用

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

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

我在类型定义方面遇到了同样的问题,并且 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 元素智能感知示例

PS:我在 DefinedType Githubhttps://github.com/DefinitelyTyped/DefinitelyTyped/issues/24419上发现了定义类型中的问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM