octokit.js icon indicating copy to clipboard operation
octokit.js copied to clipboard

[BUG]: Typescript error on paginate string input

Open josherickson opened this issue 2 years ago • 22 comments

What happened?

When using octokit.paginate, Typescript errors saying (I think?) that it does not accept a string as the first input. My understanding based on the docs and @octokit/types code is that this input can be a string, and I have confirmed that the code builds and runs if I ignore this error with // @ts-ignore. I initially had this same code but using octokit.request instead and did not have the error.

const alerts: Array<DependabotAlert> = await octokit.paginate(
  "GET /orgs/{org}/dependabot/alerts",
  {
    org: GITHUB_ORG,
    per_page: 100,
    headers: {
      "X-GitHub-Api-Version": "2022-11-28",
    },
  },
  (response) =>
    response.data.map(
      (item) =>
        <DependabotAlert>{
          createdAt: item.created_at,
          cve: item.security_advisory.cve_id,
          ecosystem: item.security_vulnerability.package.ecosystem,
          number: item.number,
          package: item.security_vulnerability.package.name,
          repository: item.repository.name,
          severity: item.security_vulnerability.severity,
          state: item.state,
          url: item.html_url,
        }
    )
);

Note: DependabotAlert is my own custom type that defines the resulting output.

What happened: Typescript error when building

No overload matches this call.
...
Argument of type 'string' is not assignable to parameter of type 'RequestInterface<object>'. ts(2769)

What I expect to happen: No Typescript error. Should build and run with "GET /orgs/{org}/dependabot/alerts" (or any string) as input.

Workaround: Add // @ts-ignore above this function call so that Typescript will ignore it and build anyways.

Versions

nodejs 16.20.0 octokit 2.0.14 @octokit/types 9.0.0 (as a sub-dependency of octokit) typescript 5.0.4

Relevant log output

error TS2769: No overload matches this call.
  Overload 1 of 9, '(route: "GET /orgs/{org}/dependabot/alerts", parameters: { org: string; } & { state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; ... 7 more ...; per_page?: number | undefined; }, mapFn: MapFunction<...>): Promise<...>', gave the following error.
    Argument of type '{ org: string; per_page: number; headers: { "X-GitHub-Api-Version": string; }; }' is not assignable to parameter of type '{ org: string; } & { state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | "runtime" | undefined; ... 6 more ...; per_page?: number | undefined; }'.
      Object literal may only specify known properties, and 'headers' does not exist in type '{ org: string; } & { state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | "runtime" | undefined; ... 6 more ...; per_page?: number | undefined; }'.
  Overload 2 of 9, '(request: RequestInterface<object>, parameters: string, mapFn: MapFunction<NormalizeResponse<OctokitResponse<any>>, DependabotAlert[]>): Promise<...>', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'RequestInterface<object>'.

  9   const alerts: Array<DependabotAlert> = await octokit.paginate(
                                                   ~~~~~~~~~~~~~~~~~
 10     "GET /orgs/{org}/dependabot/alerts",
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... 
 32       )
    ~~~~~~~
 33   );

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

josherickson avatar Apr 19 '23 23:04 josherickson

This is probably due to the fact that OpenAPI updates haven't been made on the regular. This should be fixed when https://github.com/octokit/openapi/pull/328 is merged, and the resulting schema updates trickle through all the modules

wolfy1339 avatar Apr 19 '23 23:04 wolfy1339

Hi @josherickson

Can you update your Octokit modules, and lockfiles? Then check if the problem is still present

wolfy1339 avatar May 13 '23 16:05 wolfy1339

@wolfy1339 still having an issue. Building with tsc results in similar but not exactly the same error as before:

error TS2769: No overload matches this call.
Overload 1 of 9, '(route: "GET /orgs/{org}/dependabot/alerts", parameters: { state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | ... 1 more ... | undefined; ... 6 more ...; per_page?: number | undefined; } & { ...; }, mapFn: MapFunction<...>): Promise<...>', gave the following error.
    Argument of type '{ org: string; per_page: number; headers: { "X-GitHub-Api-Version": string; }; state: string; }' is not assignable to parameter of type '{ state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | "runtime" | undefined; sort?: "created" | "updated" | undefined; ... 5 more ...; per_page?: number | undefined; } & { ...; }'.
      Object literal may only specify known properties, and 'headers' does not exist in type '{ state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | "runtime" | undefined; sort?: "created" | "updated" | undefined; ... 5 more ...; per_page?: number | undefined; } & { ...; }'.
  Overload 2 of 9, '(request: RequestInterface<object>, parameters: string, mapFn: MapFunction<NormalizeResponse<OctokitResponse<any>>, DependabotAlert[]>): Promise<...>', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'RequestInterface<object>'.

  9   const alerts: Array<DependabotAlert> = await octokit.paginate(
                                                   ~~~~~~~~~~~~~~~~~
 10     "GET /orgs/{org}/dependabot/alerts",
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... 
 34       )
    ~~~~~~~
 35   );

Code is the same as before, except for the addition of the state property:

const alerts: Array<DependabotAlert> = await octokit.paginate(
  "GET /orgs/{org}/dependabot/alerts",
  {
    org: GITHUB_ORG,
    per_page: 100,
    headers: {
      "X-GitHub-Api-Version": "2022-11-28",
    },
    state: "open"
  },
  (response) =>
    response.data.map(
      (item) =>
        <DependabotAlert>{
          ...
        }
    )
);

Versions based on updated package-lock.json:

  • node_modules/typescript: 5.0.4 (same as previously)
  • node_modules/octokit: 2.0.14 (same as previously)
  • node_modules/@octokit/types: 9.2.2 (was 9.0.0 previously)
  • node_modules/@octokit/openapi-types: 17.1.2 (was 16.0.0 previously)

This is not a huge deal for me btw. I've just ignored this line with // @ts-ignore. But happy to continue to support as much as you like.

josherickson avatar May 15 '23 23:05 josherickson

That's strange, that endpoint is defined in this package.

https://github.com/octokit/plugin-paginate-rest.js/blob/7a92a4e7f68276b57d8541850e643b8a18ef264e/src/generated/paginating-endpoints.ts#L343-L346

wolfy1339 avatar May 15 '23 23:05 wolfy1339

I think I might have an idea why that's happening.

I'll try pushing an update with updated plugins

wolfy1339 avatar May 15 '23 23:05 wolfy1339

:tada: This issue has been resolved in version 2.0.16 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

github-actions[bot] avatar May 19 '23 10:05 github-actions[bot]

@josherickson I just released an update with updated dependencies, can you check if it works now

wolfy1339 avatar May 19 '23 10:05 wolfy1339

Still no, same or similar error. Here are my new versions based on updated package-lock.json:

  • node_modules/typescript: 5.0.4 (same as originally)
  • node_modules/octokit: 2.0.16 (was 2.0.14 originally)
  • node_modules/@octokit/types: 9.2.2 (was 9.0.0 originally)
  • node_modules/@octokit/openapi-types: 17.2.0 (was 16.0.0 originally)

Here's a simplified snippet that gives the typescript build error:

import { Octokit } from "octokit";

export async function getDependabotAlerts(): Promise<void> {
  const octokit = new Octokit({ auth: process.env.GH_TOKEN });

  await octokit.paginate(
    "GET /orgs/{org}/dependabot/alerts",
    {
      org: "MyOrg",
      per_page: 100,
      headers: {
        "X-GitHub-Api-Version": "2022-11-28",
      },
      state: "open",
    },
    (response) => console.log(response)
  );
}

Full error:

error TS2769: No overload matches this call.
  Overload 1 of 9, '(route: "GET /orgs/{org}/dependabot/alerts", parameters: { state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | ... 1 more ... | undefined; ... 6 more ...; per_page?: number | undefined; } & { ...; }, mapFn: MapFunction<...>): Promise<...>', gave the following error.
    Argument of type '{ org: string; per_page: number; headers: { "X-GitHub-Api-Version": string; }; state: string; }' is not assignable to parameter of type '{ state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | "runtime" | undefined; sort?: "created" | "updated" | undefined; ... 5 more ...; per_page?: number | undefined; } & { ...; }'.
      Object literal may only specify known properties, and 'headers' does not exist in type '{ state?: string | undefined; severity?: string | undefined; ecosystem?: string | undefined; package?: string | undefined; scope?: "development" | "runtime" | undefined; sort?: "created" | "updated" | undefined; ... 5 more ...; per_page?: number | undefined; } & { ...; }'.
  Overload 2 of 9, '(request: RequestInterface<object>, parameters: string, mapFn: MapFunction<NormalizeResponse<OctokitResponse<any>>, unknown[]>): Promise<...>', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'RequestInterface<object>'.

  6   await octokit.paginate(
            ~~~~~~~~~~~~~~~~~
  7     "GET /orgs/{org}/dependabot/alerts",
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... 
 16     (response) => console.log(response)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 17   );
    ~~~

josherickson avatar May 19 '23 16:05 josherickson

I'm not sure anymore :sweat:

@gr2m @oscard0m Do you ave any ideas why this error is happening?

wolfy1339 avatar May 19 '23 16:05 wolfy1339

The types are expecting you to return an array in your function that logs the request in your simplified code

import { Octokit } from "octokit";

export async function getDependabotAlerts(): Promise<void> {
  const octokit = new Octokit({ auth: process.env.GH_TOKEN });

  await octokit.paginate(
    "GET /orgs/{org}/dependabot/alerts",
    {
      org: "octokit"
    },
    (response) => {
      console.log(response);
      return [];
    }
  );

However, whenever I try to add the header parameter, it complains about the types

wolfy1339 avatar May 19 '23 17:05 wolfy1339

This code snippet works, it's simply when passing the route as a URL that it doesn't accept request parameters

import { Octokit } from "octokit";

export async function getDependabotAlerts(): Promise<void> {
  const octokit = new Octokit({ auth: process.env.GH_TOKEN });

  await octokit.paginate(
    octokit.rest.dependabot.listAlertsForOrg,
    {
      org: "MyOrg",
      per_page: 100,
      headers: {
        "X-GitHub-Api-Version": "2022-11-28",
      },
      state: "open",
    },
    (response) => {
      console.log(response);
      return  [];
    }
  );
}

wolfy1339 avatar May 19 '23 18:05 wolfy1339

Probably relevant here... it seems like @octokit/plugin-rest-endpoint-methods has changed the version of @octokit/types it requires at some point between 7.1.3 and 7.2.3 from ^9.2.3 to ^10.0.0, and this in turns results in:

octokit.paginate.iterator(octokit.rest.repos.listReleases, { ... })

Failing with (pardon my French):

Aucune surcharge ne correspond à cet appel.
  La surcharge 1 sur 4, '(route: keyof PaginatingEndpoints, parameters?: { per_page?: number | undefined; cursor?: string | undefined; redelivery?: boolean | undefined; } | { per_page?: number | undefined; page?: number | undefined; } | ... 220 more ... | undefined): AsyncIterableIterator<...>', a généré l'erreur suivante.
    L'argument de type '{ (params?: (RequestParameters & Omit<ToOctokitParameters<{ parameters: { query?: { per_page?: number | undefined; page?: number | undefined; } | undefined; path: { owner: string; repo: string; }; }; responses: { ...; }; }>, "headers" | ... 1 more ... | "mediaType">) | undefined): Promise<...>; defaults: <O extends ...' n'est pas attribuable au paramètre de type 'keyof PaginatingEndpoints'.
  La surcharge 2 sur 4, '(route: string, parameters?: RequestParameters | undefined): AsyncIterableIterator<OctokitResponse<PaginationResults<unknown>, number>>', a généré l'erreur suivante.
    L'argument de type '{ (params?: (RequestParameters & Omit<ToOctokitParameters<{ parameters: { query?: { per_page?: number | undefined; page?: number | undefined; } | undefined; path: { owner: string; repo: string; }; }; responses: { ...; }; }>, "headers" | ... 1 more ... | "mediaType">) | undefined): Promise<...>; defaults: <O extends ...' n'est pas attribuable au paramètre de type 'string'.
  La surcharge 3 sur 4, '(request: RequestInterface<object>, parameters?: string | undefined): AsyncIterableIterator<NormalizeResponse<OctokitResponse<any>>>', a généré l'erreur suivante.
    L'argument de type '{ (params?: (RequestParameters & Omit<ToOctokitParameters<{ parameters: { query?: { per_page?: number | undefined; page?: number | undefined; } | undefined; path: { owner: string; repo: string; }; }; responses: { ...; }; }>, "headers" | ... 1 more ... | "mediaType">) | undefined): Promise<...>; defaults: <O extends ...' n'est pas attribuable au paramètre de type 'RequestInterface<object>'.
      Les types de 'defaults(...).defaults(...).endpoint.DEFAULTS' sont incompatibles entre eux.
        Impossible d'assigner le type 'object & O & O & import("/Users/rmuller/Development/cdklabs/construct-hub/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types/dist-types/RequestParameters").RequestParameters & { ...; }' au type 'object & O & O & import("/Users/rmuller/Development/cdklabs/construct-hub/node_modules/@octokit/types/dist-types/RequestParameters").RequestParameters & { baseUrl: string; method: import("/Users/rmuller/Development/cdklabs/construct-hub/node_modules/@octokit/types/dist-types/RequestMethod").RequestMethod; url?: stri...'.
          Impossible d'assigner le type 'object & O & O & RequestParameters & { baseUrl: string; method: RequestMethod; url?: string | undefined; headers: RequestHeaders & { ...; }; mediaType: { ...; }; }' au type '{ baseUrl: string; method: RequestMethod; url?: string | undefined; headers: RequestHeaders & { accept: string; "user-agent": string; }; mediaType: { format: string; previews: string[]; }; }'.
            Les types de 'mediaType.previews' sont incompatibles entre eux.
              Impossible d'assigner le type 'string[] | undefined' au type 'string[]'.
                Impossible d'assigner le type 'undefined' au type 'string[]'.ts(2769)

The error here happens because @octokit/plugin-rest-endpoint-methods gets to see & expose a whole different version of @octokit/types than @octokit/plugin-paginate-rest does.

It would appear to me that this change of dependency in @octokit/plugin-rest-endpoint-methods is semver-breaking and should have come with a new major version instead of being rolled into a minor version...

RomainMuller avatar Jun 21 '23 08:06 RomainMuller

That happens all the time when the type version of different modules mismatch for any reason, whether the changes are breaking or not.

It will get fixed over time, we still have other modules to get new major versions

wolfy1339 avatar Jun 21 '23 09:06 wolfy1339

That happens all the time when the type version of different modules mismatch for any reason, whether the changes are breaking or not.

It will get fixed over time, we still have other modules to get new major versions

Is this problem being fixed anytime soon? I know the lib still works regardless of this error, but I prefer not having any @ts-ignore comments on my code.

Harukisatoh avatar Jul 07 '23 18:07 Harukisatoh

Please be patient with us, we have many repos to take care of.

Changes are being worked on and pushed through.

We had a hold up because of a problem that came up with our switch to the fetch API from node-fetch that has been resolved just a couple minutes ago

wolfy1339 avatar Jul 07 '23 18:07 wolfy1339

@Harukisatoh The issue that was brought in this comment: https://github.com/octokit/octokit.js/issues/2439#issuecomment-1600407614 is not related to this bug report

It has been happening before that comment

wolfy1339 avatar Jul 07 '23 23:07 wolfy1339

Hey @wolfy1339, I'm sorry man, I didn't mean to be rude or anything, I appreciate the work you do with this lib.

Do we have a opened issue and a solution for the #2439 already? I tried to find it, but I couldn't. It seems that this issue is the most similar one.

Harukisatoh avatar Jul 11 '23 19:07 Harukisatoh

Unfortunately I don't believe an issue has been found yet.

Can you test the latest versions?

wolfy1339 avatar Jul 12 '23 00:07 wolfy1339

Hey, is this issue solved completely?

melihsunbul avatar Oct 19 '23 13:10 melihsunbul

There hasn't been any new comments or issues saying otherwise.

wolfy1339 avatar Oct 19 '23 14:10 wolfy1339

In case it helps anyone, I am encountering the same with GET /orgs/{org}/members and GET /orgs/{org}/repos

It looks like the headers declaration is missing in the options definition.

So this gives an error:

  const members = await octokit.paginate('GET /orgs/{org}/members', {
    org,
    per_page: 50,
    headers: {
      'X-GitHub-Api-Version': '2022-11-28',
    }
  })

with the same confusing message, which highlight the route as being wrong

No overload matches this call.
  The last overload gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'RequestInterface<object>'.ts(2769)

However, this works:

  const members = await octokit.paginate('GET /orgs/{org}/members', {
    org,
    per_page: 50,
  })

I'm working with typscript 4.8.3, and octokit 3.1.2.

timotheeg avatar Nov 29 '23 03:11 timotheeg

Indeed it does look like it's the headers option.

I don't understand why.

As stated in a previous comment, you can use the octokit.rest methods with pagination and it works fine. https://github.com/octokit/octokit.js/issues/2439#issuecomment-1555050667

wolfy1339 avatar Nov 29 '23 04:11 wolfy1339