refactor(nuxt): enhance useFetch and useLazyFetch request type#4825
refactor(nuxt): enhance useFetch and useLazyFetch request type#4825
useFetch and useLazyFetch request type#4825Conversation
Enhance the useFetch and useLazyFetch request's type by inferring nitropack's server route's string literal (InternalApi interface). supporting auto-complete and showing type hints.
✅ Deploy Preview for nuxt3-docs ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
…zyFetch` #4823 add type tests to composables suite, calling useFetch with: 1. all routes generated from server, 2. external url, 3. Request object. And should throw type error when pass in invalid request string
|
One thing that's missing is the ability to type POST request body, is there a way to implement it? |
@Rigo-m I'll look into this! |
|
Sorry that I can't help, I'm still bad a TS somehow hahaha |
Got a working code that infers the body type of a POST API, but still needs to manually export the type from the API file and change the auto-generated InternalApi interface, or have to make some change to nitropack (and maybe h3) to make the implementation cleaner. hacky method // .nuxt/types/nitro.d.ts
declare module 'nitropack' {
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T
interface InternalApi {
// turn value of InternalApi in to tuple, with index 1 being the body type
'/api/test': [Awaited<ReturnType<typeof import('../../server/api/test').default>>, import('../../server/api/test').BodyType]
'/__nuxt_error': [Awaited<ReturnType<typeof import('../../../packages/nuxt/src/core/runtime/nitro/renderer').default>>,'']
}
}
// server/api/test.ts
export type BodyType = {tag:string, index:number } // export the manually defined type
export default defineEventHandler(async (event) => {
const body = await useBody<BodyType>(event)
return { result: body.tag }
})
// composable/fetch.ts
export declare type FetchRequestUrl =
Exclude<keyof InternalApi, '/__nuxt_error'>
| (`${string}${'/'|'.'}${string}` & {})
| Exclude<FetchRequest, string>
interface ExFetchOptions<Route extends FetchRequestUrl> extends FetchOptions {
body?: Route extends keyof InternalApi ? InternalApi[Route][1] : FetchOptions['body']
}
export interface UseFetchOptions<
DataT,
ReqT extends FetchRequestUrl,
Transform extends _Transform<DataT, any> = _Transform<DataT, DataT>,
PickKeys extends KeyOfRes<Transform> = KeyOfRes<Transform>
> extends AsyncDataOptions<DataT, Transform, PickKeys>, ExFetchOptions<ReqT> {
key?: string
}
// usage
const { data } = useFetch('/api/test', { // have to update nitropack's type to correctly infer data type
method: 'POST',
body: { tag: '3', index: 2 } // body will be type 'BodyType '
}) |
|
Maybe a clean solution could be manually typing body by extending nuxt schema like we do for manually tiping useRuntimeConfig? |
|
I love this idea. I think rather than seeking to implement within ... and then update this PR accordingly. WDYT @pi0? |
|
I also love to try this idea! Indeed nitro seems better place to implement types for |
Sounds great! I implement it in Nuxt first as I wasn't sure if this should be implemented in nitropack. But after some digging and trying to implement type hint for POST body yesterday, I also found out that the codes to updates are mostly in nitropack. mainly:
I'll find some time to dig into it 👍 |
Hey, @danielroe @pi0 would like to get some suggestions/notices (if any) on point 2 before I start, for changing the |
UpdateImplementing this enhancement in |
|
@didavid61202 Since nitrojs/nitro#208 is landed, do you mind to rework this PR? Thanks! |
|
I'm on it! 🚀 |
…-request-url-type
I would hide all |
updated in b49385c, excluding all |
|
@didavid61202 Maybe we can move this fix directly to Nitro and avoid workaround? I can quickly merge it for nitro and this after that :) |
sure, on it! |
|
Looking great! There were a couple of workarounds in 7e89fe8 that I think we can now remove as well, if you're up for it 😊 |
Can we directly use |
|
sure, on it! will see what I can do 👍 |
got it! |
useFetch and useLazyFetch request type #4823useFetch and useLazyFetch request type #4823
useFetch and useLazyFetch request type #4823useFetch and useLazyFetch request type
useFetch and useLazyFetch request typeuseFetch and useLazyFetch request type
|
Thanks for working on this @didavid61202 @danielroe <3 |
Updates
awaiting fix in nitro for
NitroFetchRequesttype to support string type (FixNitroFetchRequesttype to supportstringtype nitrojs/nitro#225)update at 2022/5/11
updated this PR according to
unjs/nitro's newNitroFetchRequesttype (enhance $fetch's request type infer from generated InternalApi interface nitrojs/nitro#208)update at 2022/5/11
Implementing this enhancement in the
unjs/nitrorepo for$fetchfirst (enhance $fetch's request type infer from generated InternalApi interface nitrojs/nitro#208), and will update this PR accordingly.update at 2022/5/7
Enhance the useFetch and useLazyFetch request's type by inferring nitropack's server route's string literal (InternalApi interface). supporting auto-complete and showing type hints.
🔗 Linked issue
Resolve nuxt/nuxt#13934
❓ Type of change
📚 Description
Enhance the
useFetchanduseLazyFetchrequest's type by inferring nitropack's server route's string literal (InternalApi interface).This will provide better DX and prevent typos while using
useFetchanduseLazyFetchby supporting auto-complete and showing type hints when entering the request. And should still be able to pass other valid request URLs likehttps://example.com/apior Request object likenew Request('/api/test')Usage scenario
assume project contains
server/api/test.ts📝 Checklist