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

Expose request and response types in a simple way #31

Closed
huang-julien opened this issue Mar 17, 2024 · 6 comments · Fixed by #64
Closed

Expose request and response types in a simple way #31

huang-julien opened this issue Mar 17, 2024 · 6 comments · Fixed by #64

Comments

@huang-julien
Copy link
Contributor

Hey thanks for your module !

I'm coming from open-api-generator with axios-typescript which exposes enum and types directly from what's generated.

It could be nice to expose directly quer/params and response types from generation and maybe adding them to auto-import ?

Currently the only way to retrieve thse types is to import from the operations type:

import type { operations } from "#build/types/nuxt-open-fetch/schemas/---.ts"

function parms (param: operations['...']['query']) {}
@enkot
Copy link
Owner

enkot commented Mar 19, 2024

Hi @huang-julien,
I like the idea.
There is a PR in openapi-typescript to solve this problem openapi-ts/openapi-typescript#1260.

Unfortunately, the author said he won't be working on it anymore, so I'll give it a shot :)

The main problem as I understand is this one:

the proposal to have top-level “friendly names” doesn’t work for many schemas, because you’re allowed to use characters in component names that aren’t JS-safe. So we’d have to rename them somehow, while preventing conflicts.

@huang-julien
Copy link
Contributor Author

huang-julien commented Mar 19, 2024

interesting 👀 ... I'll be waiting then.
i'm just doing a workaround ATM:

import type { operations } from '#build/types/nuxt-open-fetch/schemas/bff'

export type OperationParameters<T extends keyof operations> = 'parameters' extends keyof operations[T]
	? operations[T]['parameters']
	: never

// example
function (t: Partial<OperationParameters<'GetPet'>['query']>) {
    $fetch('...', { query : t })
}

It does work but def not my fav way of using types haha

I don't have a solution for enums yet. For now enums generated from open-api-generator with axios-typescript are compatible with openapi-typescript

@enkot
Copy link
Owner

enkot commented Mar 27, 2024

Created a PR to export types with friendly names openapi-ts/openapi-typescript#1599.
But it's an open question which level of nested types for paths should be aliased and what is the most convenient way to use them:

RequestEnterpriseAdminListGlobalWebhooks['query']
// or
RequestEnterpriseAdminListGlobalWebhooksQuery
// or
EnterpriseAdminListGlobalWebhooksQuery
// etc

Good news is that enums generation is supported out of the box in v7 by using --enum flag :)

@jonkri
Copy link

jonkri commented Jun 18, 2024

I'm not sure if it's relevant for this issue. 😅 I'm wondering how I can access the response type for a certain request.

I would like to type my Pinia store without having to type something like this:

export const useStore = defineStore("test", {
  // ...
  state: () => ({
    token: null as null | string,
    userInfo: null as {
      deactivate?: string | undefined;
      email: string;
      id: string;
      instances: {
        id: string;
        name: string;
      }[];
      name: string;
      phone?: string | undefined;
      roles: string[];
    } | null
  })
});

Ideally the code would look something like this:

export const useStore = defineStore("test", {
  // ...
  state: () => ({
    token: null as null | string,
    userInfo: null as UserInfoByToken | null
  })
});

Here's the code I'm using to set userInfo:

const { data, error } = await useAuthService(
  "/user-info-by-token/{token}",
  {
    path: { token: this.token }
  }
);

this.userInfo = data.value;

@jd-solanki
Copy link

jd-solanki commented Jun 19, 2024

@jonkri I suggest opening new issue for this. However, here's my suggestion as per what I understand you're trying to do:

  1. You can import the type and assign it

    import type { operations } from '#build/types/open-fetch/schemas/api'
    
    export const useStore = defineStore("test", {
      // ...
      state: () => ({
        token: null as null | string,
    
    	// You can get type from operations. You've to update below type according to your API
        userInfo: null as operations['...']['...'] | null,
      })
    });
  2. Additionally, I've also created few type utils for myself. These are custom made so there can be chances of improving it. I'm using it for my personal use and they're fine till now. This might look confusing so if you are beginner avoid this.

    import type { operations } from '#build/types/open-fetch/schemas/api'
    
    export type ApiResponse<T extends keyof operations, R extends keyof operations[T]['responses']> = operations[T]['responses'][R] extends { content: { 'application/json': infer U } }
      ? U
      : never
    
    export type ApiRequestBody<T extends keyof operations> = operations[T]['requestBody'] extends { content: { 'application/json': infer U } }
      ? U
      : never
    
    export type ApiRequestQueryParams<T extends keyof operations> = operations[T]['parameters'] extends { query?: infer U } ? U : never

    Here's how you can use it:

    import type { operations } from '#build/types/open-fetch/schemas/api'
    
    export const useStore = defineStore("test", {
      // ...
      state: () => ({
        token: null as null | string,
    
    	// You can get type from operations. You've to update below type according to your API
        userInfo: null as ApiResponse<'get_users__user_id', 200>,
      })
    });

@FBenkhalifa
Copy link

FBenkhalifa commented Sep 5, 2024

How about this:

import type { paths } from '#open-fetch-schemas/auth-fetch'

type Paths = keyof paths
type Methods<path extends Paths> = keyof paths[path]
type AuthService<pathT extends Paths, methodT extends Methods<pathT>> = paths[pathT][methodT]['responses']['200']['content']['application/json']

let userInfo: AuthService<'/user-info-by-token/{token}', 'get'>

userInfo should then be properly typed.

@enkot enkot linked a pull request Sep 7, 2024 that will close this issue
@enkot enkot closed this as completed in #64 Sep 7, 2024
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

Successfully merging a pull request may close this issue.

5 participants