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: