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

Can't create plugins with typescript #1407

Closed
remborg opened this issue May 25, 2020 · 5 comments
Closed

Can't create plugins with typescript #1407

remborg opened this issue May 25, 2020 · 5 comments

Comments

@remborg
Copy link

remborg commented May 25, 2020

Using cheerio with typescript works fine until I try to create a plugin:

import cheerio from 'cheerio';

const html: string = `
<ul id="fruits">
    <li class="apple">Apple</li>
    <li class="orange">Orange</li>
    <li class="pear">Pear</li>
</ul>`;

const $ = cheerio.load(html, {
    normalizeWhitespace: true
});

$.prototype.logHtml = function () {
    console.log(this.html());
};

$('#fruits').logHtml();

Typescript returns me error:

Property 'logHtml' does not exist on type 'Cheerio'.ts(2339)

This is normal, since logHtml is not part of '@types/cheerio'. So I've tried to do some module augmentation by adding this after the import:

declare module "cheerio" {
    interface Cheerio {
        logHtml(): void
    }
}

The previous error is still there and I get a new one:

Cannot augment module 'cheerio' because it resolves to a non-module entity.ts(2671)

I'm I doing something wrong or is this an issue with the way the module is created?

EDIT: I'm using node v12.16.3, tsc v3.9.3, @types/cheerio v0.22.18 and cheerio v1.0.0-rc.3

@remborg
Copy link
Author

remborg commented May 25, 2020

I've found a similar issue in another library:
googleapis/google-auth-library-nodejs#177

A workaround here is to use the require syntax const cheerio = require('cheerio'); instead of the import .
Not great but typescript doesn't complain anymore. You loose intellisense in vs-code too.

My tsconfig file is as follow:

{
    "compilerOptions": {
        "module": "commonjs",
        "rootDir": "src",
        "moduleResolution": "node",
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "noImplicitAny": true,
    },
    "include": [
        "src/"
    ],
    "exclude": [
        "node_modules"
    ]
}

@fb55
Copy link
Member

fb55 commented May 25, 2020

Typescript interfaces are open, so you should be able to add methods to them like this.

@fb55 fb55 closed this as completed May 25, 2020
@remborg
Copy link
Author

remborg commented May 26, 2020

Thanks for the link but this solution doesn't work.
vscode tells me that the new interface is Cheerio' is declared but never used.ts(6196)
And the custom function still has 'Property logHtml' does not exist on type 'Cheerio'.ts(2339)

Here is the full code:

import cheerio from 'cheerio';

const html: string = `
<ul id="fruits">
<li class="apple">Apple</li>
<li class="orange">Orange</li>
<li class="pear">Pear</li>
</ul>
`;
const $ = cheerio.load(html, {
    normalizeWhitespace: true
});

interface Cheerio {
    logHtml(): void
}

$.prototype.logHtml = function () {
    console.log(this.html());
};

$('#fruits').logHtml();

@remborg
Copy link
Author

remborg commented May 26, 2020

I've managed to get typescript happy, thanks to this post: microsoft/TypeScript#7148 (comment)

I had to define my plugin globally with:

declare global {
    interface Cheerio {
        logHtml(): void
    }
}

@fb55
Copy link
Member

fb55 commented Jun 10, 2020

Awesome, thanks for updating @remborg!

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

No branches or pull requests

2 participants