Skip to content

Commit

Permalink
feat(useAxios): improve type (#2208)
Browse files Browse the repository at this point in the history
Co-authored-by: vaakian X <30516060+vaakian@users.noreply.github.com>
  • Loading branch information
azaleta and vaakian committed Sep 21, 2022
1 parent a1d93d3 commit f3ae7c8
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
38 changes: 38 additions & 0 deletions packages/integrations/useAxios/index.test.ts
Expand Up @@ -210,4 +210,42 @@ describe('useAxios', () => {
expect(onRejected).toBeCalledTimes(0)
}, onRejected)
})

test('use generic type', async () => {
interface ReqType {
title: string
body: string
userId: number
}

interface ResType {
id: number
title: string
body: string
userId: number
}
const typeConfig: AxiosRequestConfig<ReqType> = {
method: 'POST',
}
const { isLoading, then, execute } = useAxios<ResType, ReqType>('/posts', typeConfig, instance, options)
expect(isLoading.value).toBeFalsy()
const requestData: ReqType = {
title: 'title',
body: 'body',
userId: 123,
}
execute({ data: requestData })
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

await then((result) => {
expect(result.data).toBeDefined()
expect(result.data.value?.title).toBe('title')
expect(result.data.value?.body).toBe('body')
expect(result.data.value?.userId).toBe(123)
expect(result.data.value?.id).toBeDefined()
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
}, onRejected)
})
})
40 changes: 20 additions & 20 deletions packages/integrations/useAxios/index.ts
Expand Up @@ -4,11 +4,11 @@ import { isString, until } from '@vueuse/shared'
import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, CancelTokenSource } from 'axios'
import axios from 'axios'

export interface UseAxiosReturn<T> {
export interface UseAxiosReturn<T, D> {
/**
* Axios Response
*/
response: ShallowRef<AxiosResponse<T> | undefined>
response: ShallowRef<AxiosResponse<T, D> | undefined>

/**
* Axios response data
Expand Down Expand Up @@ -74,17 +74,17 @@ export interface UseAxiosReturn<T> {
*/
isCanceled: Ref<boolean>
}
export interface StrictUseAxiosReturn<T> extends UseAxiosReturn<T> {
export interface StrictUseAxiosReturn<T, D> extends UseAxiosReturn<T, D> {
/**
* Manually call the axios request
*/
execute: (url?: string | AxiosRequestConfig, config?: AxiosRequestConfig) => PromiseLike<StrictUseAxiosReturn<T>>
execute: (url?: string | AxiosRequestConfig<D>, config?: AxiosRequestConfig<D>) => PromiseLike<StrictUseAxiosReturn<T, D>>
}
export interface EasyUseAxiosReturn<T> extends UseAxiosReturn<T> {
export interface EasyUseAxiosReturn<T, D> extends UseAxiosReturn<T, D> {
/**
* Manually call the axios request
*/
execute: (url: string, config?: AxiosRequestConfig) => PromiseLike<EasyUseAxiosReturn<T>>
execute: (url: string, config?: AxiosRequestConfig<D>) => PromiseLike<EasyUseAxiosReturn<T, D>>
}
export interface UseAxiosOptions {
/**
Expand All @@ -93,24 +93,24 @@ export interface UseAxiosOptions {
*/
immediate?: boolean
}
type OverallUseAxiosReturn<T> = StrictUseAxiosReturn<T> | EasyUseAxiosReturn<T>
type OverallUseAxiosReturn<T, D> = StrictUseAxiosReturn<T, D> | EasyUseAxiosReturn<T, D>

export function useAxios<T = any>(url: string, config?: AxiosRequestConfig, options?: UseAxiosOptions): StrictUseAxiosReturn<T> & PromiseLike<StrictUseAxiosReturn<T>>
export function useAxios<T = any>(url: string, instance?: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn<T> & PromiseLike<StrictUseAxiosReturn<T>>
export function useAxios<T = any>(url: string, config: AxiosRequestConfig, instance: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn<T> & PromiseLike<StrictUseAxiosReturn<T>>
export function useAxios<T = any>(config?: AxiosRequestConfig): EasyUseAxiosReturn<T> & PromiseLike<EasyUseAxiosReturn<T>>
export function useAxios<T = any>(instance?: AxiosInstance): EasyUseAxiosReturn<T> & PromiseLike<EasyUseAxiosReturn<T>>
export function useAxios<T = any>(config?: AxiosRequestConfig, instance?: AxiosInstance): EasyUseAxiosReturn<T> & PromiseLike<EasyUseAxiosReturn<T>>
export function useAxios<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>, options?: UseAxiosOptions): StrictUseAxiosReturn<T, D> & PromiseLike<StrictUseAxiosReturn<T, D>>
export function useAxios<T = any, D = any>(url: string, instance?: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn<T, D> & PromiseLike<StrictUseAxiosReturn<T, D>>
export function useAxios<T = any, D = any>(url: string, config: AxiosRequestConfig<D>, instance: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn<T, D> & PromiseLike<StrictUseAxiosReturn<T, D>>
export function useAxios<T = any, D = any>(config?: AxiosRequestConfig<D>): EasyUseAxiosReturn<T, D> & PromiseLike<EasyUseAxiosReturn<T, D>>
export function useAxios<T = any, D = any>(instance?: AxiosInstance): EasyUseAxiosReturn<T, D> & PromiseLike<EasyUseAxiosReturn<T, D>>
export function useAxios<T = any, D = any>(config?: AxiosRequestConfig<D>, instance?: AxiosInstance): EasyUseAxiosReturn<T, D> & PromiseLike<EasyUseAxiosReturn<T, D>>

/**
* Wrapper for axios.
*
* @see https://vueuse.org/useAxios
*/
export function useAxios<T = any>(...args: any[]): OverallUseAxiosReturn<T> & PromiseLike<OverallUseAxiosReturn<T>> {
export function useAxios<T = any, D = any>(...args: any[]): OverallUseAxiosReturn<T, D> & PromiseLike<OverallUseAxiosReturn<T, D>> {
const url: string | undefined = typeof args[0] === 'string' ? args[0] : undefined
const argsPlaceholder = isString(url) ? 1 : 0
let defaultConfig: AxiosRequestConfig = {}
let defaultConfig: AxiosRequestConfig<D> = {}
let instance: AxiosInstance = axios
let options: UseAxiosOptions = { immediate: !!argsPlaceholder }

Expand Down Expand Up @@ -160,15 +160,15 @@ export function useAxios<T = any>(...args: any[]): OverallUseAxiosReturn<T> & Pr
isFinished.value = !loading
}
const waitUntilFinished = () =>
new Promise<OverallUseAxiosReturn<T>>((resolve, reject) => {
new Promise<OverallUseAxiosReturn<T, D>>((resolve, reject) => {
until(isFinished).toBe(true)
// eslint-disable-next-line @typescript-eslint/no-use-before-define
.then(() => resolve(result))
.catch(reject)
})
const then: PromiseLike<OverallUseAxiosReturn<T>>['then'] = (onFulfilled, onRejected) =>
const then: PromiseLike<OverallUseAxiosReturn<T, D>>['then'] = (onFulfilled, onRejected) =>
waitUntilFinished().then(onFulfilled, onRejected)
const execute: OverallUseAxiosReturn<T>['execute'] = (executeUrl: string | AxiosRequestConfig | undefined = url, config: AxiosRequestConfig = {}) => {
const execute: OverallUseAxiosReturn<T, D>['execute'] = (executeUrl: string | AxiosRequestConfig<D> | undefined = url, config: AxiosRequestConfig<D> = {}) => {
error.value = undefined
const _url = typeof executeUrl === 'string'
? executeUrl
Expand All @@ -186,7 +186,7 @@ export function useAxios<T = any>(...args: any[]): OverallUseAxiosReturn<T> & Pr
return { then }
}
if (options.immediate && url)
(execute as StrictUseAxiosReturn<T>['execute'])()
(execute as StrictUseAxiosReturn<T, D>['execute'])()

const result = {
response,
Expand All @@ -203,7 +203,7 @@ export function useAxios<T = any>(...args: any[]): OverallUseAxiosReturn<T> & Pr
isCanceled: isAborted,
abort,
execute,
} as OverallUseAxiosReturn<T>
} as OverallUseAxiosReturn<T, D>

return {
...result,
Expand Down

0 comments on commit f3ae7c8

Please sign in to comment.