Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript error "ts(4023)" caused by index.d.ts #1692

Closed
rondonjon opened this issue Jan 21, 2021 · 3 comments
Closed

Typescript error "ts(4023)" caused by index.d.ts #1692

rondonjon opened this issue Jan 21, 2021 · 3 comments

Comments

@rondonjon
Copy link

I am getting TypeScript error ts(4023) in my application when I try to use any of the types in the cheerio namespace as return types.

import { load } from "cheerio";
export const parseHtml = async (source: string | Buffer) => load(source);
Exported variable 'parseHtml' has or is using name 'cheerio.Root' from external module "/.../node_modules/cheerio/types/index" but cannot be named.

The compiler can't use cheerio.Root as return type because Root is in the cheerio namespace and that namespace is currently not exported.

I've already spent a few hours finding a possible fix, here is what I found so far:

Approach no. 1 - preserving the namespace (currently not working)

A common pattern which is used by @types/React and many others is to export both, API and namespace.

export = React;
export as namespace React;

But this only seems to work if all API functions are direct members of the namespace:

declare namespace cheerio {
  function load(...)
}

This is currently not the case. It seems that the API definition is currently distributed over three abstract interfaces (Selector, Root, and CheerioAPI) inside the namespace, whereas the actual API instance (which is then exported as default) resides outside the namespace.

While the members of two of these interfaces, Root and CheerioAPI, could actually be unwrapped very easily, ...

  //interface CheerioAPI extends Root {
    const version: string;
    function load(html: string | { toString(): string }, options?: CheerioParserOptions): Root;
    function load(element: Element, options?: CheerioParserOptions): Root;
  //}

... I am still struggling with the third, Selector, which describes the signature of the default export when it is used as a function:

interface Selector {
    (selector: string): Cheerio;
    (selector: string, context: string): Cheerio;

As much as I like the namespace idea, for me, with rather limited Typescript experience, this is a dead end.

Approach no. 2 - without the namespace (working)

So I tried something completely different, removed the cheerio namespace altogether and marked all its members as direct exports. While this is clearly not the "prettiest" solution, it is at least a "working" solution; the TypeScript error has disappeared.

Merge Request???

For this latter solution, I could contribute a MR if desired.

@rondonjon rondonjon changed the title Typescript errors caused by index.d.ts Typescript error "ts(4023)" caused by index.d.ts Jan 21, 2021
@rondonjon
Copy link
Author

OK, looks like I just found the missing piece for an Approach no. 3 which preserves the namespace 😄

And it is ridiculously simple 🤣

Updated the merge request.

@5saviahv
Copy link
Contributor

Nice work, I am not very familiar with all this typescript stuff, but I will try it.

@rondonjon
Copy link
Author

Closing my own PR in favor of #1682, which also solves the problem for me, but in a more compatible manner, according to Default Exports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants