![](/img/trans.png)
[英]Typescript - How to dynamically type an object with keys from a dynamic array of objects
[英]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 环境,并在那里自动为您解析。 但是,此过程将删除对象的任何不可序列化的属性。 这就是你最终得到许多空对象的原因。
要获取页面上元素的句柄,您需要使用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)
...
PS:我在 DefinedType Githubhttps://github.com/DefinitelyTyped/DefinitelyTyped/issues/24419上发现了定义类型中的问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.