Skip to content

'GET /repos/{owner}/{repo}' API response status type is 200, but should include other codes. #445

Open
@ranmocy

Description

@ranmocy

What happened?

Typescript 4.7.4

Minimal reproducible code:

  const octokit = new Octokit()
  const response = await octokit.request(
    'GET /repos/{owner}/{repo}', {
      owner: '',
      repo: '',
    })
  if (response.status === 404) {  // <= Typescript error: TS2367: This condition will always return 'false' since the types '200' and '404' have no overlap.
    throw new Error('Repo not found')
  }

image

What did you expect to happen?

@octokit/openapi-types already defines different responses codes including 404:

  /** The `parent` and `source` objects are present when the repository is a fork. `parent` is the repository this repository was forked from, `source` is the ultimate source for the network. */
  "repos/get": {
    parameters: {
      path: {
        /** The account owner of the repository. The name is not case sensitive. */
        owner: components["parameters"]["owner"];
        /** The name of the repository. The name is not case sensitive. */
        repo: components["parameters"]["repo"];
      };
    };
    responses: {
      /** Response */
      200: {
        content: {
          "application/json": components["schemas"]["full-repository"];
        };
      };
      301: components["responses"]["moved_permanently"];
      403: components["responses"]["forbidden"];
      404: components["responses"]["not_found"];
    };
  };

So I expect response.status type should be 200 | 301 | 403 | 404

What the problem might be

Maybe because Endpoints.ExtractOctokitResponse doesn't handle error response codes?

declare type SuccessStatuses = 200 | 201 | 202 | 204;
declare type RedirectStatuses = 301 | 302;
declare type EmptyResponseStatuses = 201 | 204;
declare type KnownJsonResponseTypes = "application/json" | "application/scim+json" | "text/html";
declare type SuccessResponseDataType<Responses> = {
    [K in SuccessStatuses & keyof Responses]: GetContentKeyIfPresent<Responses[K]> extends never ? never : OctokitResponse<GetContentKeyIfPresent<Responses[K]>, K>;
}[SuccessStatuses & keyof Responses];
declare type RedirectResponseDataType<Responses> = {
    [K in RedirectStatuses & keyof Responses]: OctokitResponse<unknown, K>;
}[RedirectStatuses & keyof Responses];
declare type EmptyResponseDataType<Responses> = {
    [K in EmptyResponseStatuses & keyof Responses]: OctokitResponse<never, K>;
}[EmptyResponseStatuses & keyof Responses];
declare type GetContentKeyIfPresent<T> = "content" extends keyof T ? DataType<T["content"]> : DataType<T>;
declare type DataType<T> = {
    [K in KnownJsonResponseTypes & keyof T]: T[K];
}[KnownJsonResponseTypes & keyof T];
declare type ExtractOctokitResponse<R> = "responses" extends keyof R ? SuccessResponseDataType<R["responses"]> extends never ? RedirectResponseDataType<R["responses"]> extends never ? EmptyResponseDataType<R["responses"]> : RedirectResponseDataType<R["responses"]> : SuccessResponseDataType<R["responses"]> : unknown;

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugSomething isn't working as documented, or is being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions