Deno seems to assume wrong return type (Puppeteer)

With the following code, I get an type error which I do not expect:
const element: ElementHandle | null = await page.$('span.label-status');
const shouldBeString: string = await element?.$eval('a', (el): string => el.innerText);
const element: ElementHandle | null = await page.$('span.label-status');
const shouldBeString: string = await element?.$eval('a', (el): string => el.innerText);
On the shouldBeString I receive the following type error:
Type 'ElementHandle<any> | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
Type 'ElementHandle<any> | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
Even though $eval() returns any type: https://pptr.dev/api/puppeteer.page._eval Anyone have an idea how to fix this?
Page.$eval() method | Puppeteer
This method runs document.querySelector within the page and passes the result as the first argument to the pageFunction.
10 Replies
Kyiro
Kyiro11mo ago
This isn't a Deno issue but just how TypeScript works
const shouldBeString = ... as string | undefined;
if (!shouldBeString) throw new Error("Eval failed");
// Should be a string now
const shouldBeString = ... as string | undefined;
if (!shouldBeString) throw new Error("Eval failed");
// Should be a string now
AapoAlas
AapoAlas11mo ago
Undefined at least is very much correct: null?.eval() becomes undefined.
Max van der Velde
This seems to work indeed, thanks
AapoAlas
AapoAlas11mo ago
To me it does look like TS should be properly determining the return value of the eval handler but I can't really say since I'm not on a computer.
Max van der Velde
Still a bit confused as to why TypeScript says $eval returns ElementHandle<any> | undefined
Kyiro
Kyiro11mo ago
Beacuse you're using the ?. operator
Kyiro
Kyiro11mo ago
Optional chaining (?.) - JavaScript | MDN
The optional chaining (?.) operator accesses an object's property or calls a function. If the object accessed or function called using this operator is undefined or null, the expression short circuits and evaluates to undefined instead of throwing an error.
Max van der Velde
No I mean specifically the ElementHandle<any> part. Undefined makes sense
Kyiro
Kyiro11mo ago
Ah, that should just be what puppeteer returns right?
Max van der Velde
but $eval should return : Promise<Awaited<ReturnType<Func>>> Yes exactly According to the docs it should be this