plugin-paginate-rest.js
plugin-paginate-rest.js copied to clipboard
TypeScript types appear to be incorrect for paginate() on apps.listReposAccessibleToInstallation
Hey there.
When running await paginate(...)
on apps.listReposAccessibleToInstallation
, the TypeScript inferred data type is not correct.
// context is an Octokit with an installation.id
const repos = await context.paginate(context.apps.listReposAccessibleToInstallation, {
per_page: 100,
});
// TypeScript compiler/VSCode sees `repos` as:
// {
// total_count: number,
// repositories: { id: number, /*...*/ }[ ],
// repository_selection: ?string
// }
But really at runtime it contains repositories
data array:
console.log(repos)
// [
// { id: 123, /*...*/ },
// { id: 456, /*...*/ }
// ]
Workaround
// FIXME: Have been doing this as a workaround.
const installationRepos = repos.repositories ?? repos;
installationRepos.forEach(/*...*/);
Hmm I have a test for this exact endpoint and TS compiles without error:
https://github.com/octokit/plugin-paginate-rest.js/blob/184262e8e5b65f49c58322dcad1313320022b8c3/test/validate-typescript.ts#L173-L187
Might this be a problem with a different TS config or TS version?
Note that we do create a union between the actual endpoint types which is { total_count, repositories, ... }
and our normalized format that we do within @octokit/plugin-paginate-rest
which is { ...repositoryProperties}[]
. We do that because some of the returned properties from the API cannot be derived from another place, so you basically get an array with custom properties such as .total_count
closing due to inactivity
Might this be a problem with a different TS config or TS version?
Possibly! I believe I was on latest, not sure if VSCode pulls in a different bin though 👍
Thanks for having a look @gr2m
Hi,
we have exact same issue.
Code:
repos = await this.appInstallsClient.paginate(
this.appInstallsClient.apps.listReposAccessibleToInstallation,
{
per_page: 100,
headers: {
'If-None-Match': this.reposResponse?.headers.etag,
},
},
response =>
response.data.filter(repository => isActiveRepository(repository)),
);
Typescript expects an object ( { repositories, total_count, ..} ). Typescript Version: ^4.4.4
I am also seeing this issue. @gr2m can you reopen please?
Note that @octokit is currently unmaintained, subscribe to https://github.com/octokit/octokit.js/discussions/620#discussioncomment-1472174 for updates
I saw the same problem today, after updating to [email protected]
and [email protected]
. Typescript complained about that it's no longer an array with .length
attribute, but rather the object.
Anyway @reececomo thanks a lot for providing a workaround. That works flawless 👍
No problem @Shegox! Sorry it has to be this way 😓
I can confirm that this is happening to me locally when cloning this repo in VSCode with TypeScript 5.0.4, but not when running the test:ts
script with the same TypeScript version.
The type of the returned value for the pagination is not an array.
https://github.com/octokit/plugin-paginate-rest.js/blob/9240b2f12b273daebbd28b82d5e84e25fba457c7/src/types.ts#L178-L189
Maybe the returned type should be Promise<NormalizeResponse<OctokitTypes.GetResponseTypeFromEndpointMethod<R>>["data"][]>;
I've stumbled into this issue as well. If it helps anyone else until this is resolved, I'm doing this as a workaround:
// N.B. I've only included the properties I happen to use here.
type InstallationRepository = {
name: string;
full_name: string;
owner: {
login: string;
};
default_branch: string;
archived: boolean;
fork: boolean;
html_url: string;
is_template: boolean;
topics: string[];
};
const repositories = (await octokit.paginate(
octokit.rest.apps.listReposAccessibleToInstallation,
{ per_page: 100 }
)) as unknown as InstallationRepository[];
I have the same issue i did this to solve
const repositories = (await octokit.paginate(
octokit.rest.apps.listReposAccessibleToInstallation,
)) as unknown as Awaited<
ReturnType<typeof octokit.rest.apps.listReposAccessibleToInstallation>
>["data"]["repositories"];
For completeness, other than listReposAccessibleToInstallation
, another method that is affected by this issue is listInstallationsForAuthenticatedUser
.
Here is what I've figured,
In the pagination code, we check for and delete the following keys from the data object. https://github.com/octokit/plugin-paginate-rest.js/blob/0de101185bd8bd9f6753fb8344f1a5df113ad2b6/src/normalize-paginated-list-response.ts#L39-L41
That isn't represented in the types.
Here is a little snippet that can return only the paginated data for the types for any endpoint
type Data = Awaited<ReturnType<typeof octokit.rest.apps.listReposAccessibleToInstallation>>['data'];
type GetPaginationData<Data> = Data extends { total_count: number }
? Data extends { url: any }
? Data
: Data[Exclude<
keyof Data,
"repository_selection" | "total_count" | "incomplete_results"
>]
: Data;
type PaginationDataResult = GetPaginationData<Data>;
Simply adding this code to the definitions should help with these situations.
:tada: This issue has been resolved in version 11.3.5 :tada:
The release is available on:
Your semantic-release bot :package::rocket: