Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8502f46

Browse files
huang-julienantfu
andauthored
fix(useAxios): narrow type of data when initialValue is provided (#4419)
Co-authored-by: Anthony Fu <[email protected]>
1 parent 3ca0dea commit 8502f46

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

packages/integrations/useAxios/index.test.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { RawAxiosRequestConfig } from 'axios'
2+
import type { UseAxiosOptions, UseAxiosOptionsBase, UseAxiosOptionsWithInitialData } from '.'
23
import axios from 'axios'
3-
import { describe, expect, it, vi } from 'vitest'
4+
import { describe, expect, expectTypeOf, it, vi } from 'vitest'
45
import { nextTick } from 'vue'
56
import { useAxios } from '.'
67
import { isBelowNode18 } from '../../.test'
@@ -403,4 +404,19 @@ describe.skipIf(isBelowNode18)('useAxios', () => {
403404
expect(isFinished.value).toBeTruthy()
404405
expect(isLoading.value).toBeFalsy()
405406
})
407+
408+
it('expect data type to not be undefined with initialData', async () => {
409+
const o: UseAxiosOptions<number> = { ...options, initialData: 1 }
410+
expectTypeOf(o.initialData).toBeNumber()
411+
expectTypeOf(o).toEqualTypeOf<UseAxiosOptionsWithInitialData<number>>()
412+
expectTypeOf(o).not.toEqualTypeOf<UseAxiosOptionsBase<number>>()
413+
const d = useAxios<number>(url, config, o)
414+
expectTypeOf(d.data.value).toBeNumber()
415+
})
416+
417+
it('expect data type to maybe be undefined without initialData', async () => {
418+
const d = useAxios<number>(url, config, { ...options })
419+
420+
expectTypeOf(d.data.value).toEqualTypeOf<number | undefined>()
421+
})
406422
})

packages/integrations/useAxios/index.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { noop, until } from '@vueuse/shared'
44
import axios, { AxiosError } from 'axios'
55
import { ref, shallowRef } from 'vue'
66

7-
export interface UseAxiosReturn<T, R = AxiosResponse<T>, _D = any> {
7+
export interface UseAxiosReturn<T, R = AxiosResponse<T>, _D = any, O extends UseAxiosOptions = UseAxiosOptions<T>> {
88
/**
99
* Axios Response
1010
*/
@@ -13,7 +13,7 @@ export interface UseAxiosReturn<T, R = AxiosResponse<T>, _D = any> {
1313
/**
1414
* Axios response data
1515
*/
16-
data: Ref<T | undefined>
16+
data: O extends UseAxiosOptionsWithInitialData<T> ? Ref<T> : Ref<T | undefined>
1717

1818
/**
1919
* Indicates if the request has finished
@@ -50,19 +50,19 @@ export interface UseAxiosReturn<T, R = AxiosResponse<T>, _D = any> {
5050
*/
5151
isCanceled: Ref<boolean>
5252
}
53-
export interface StrictUseAxiosReturn<T, R, D> extends UseAxiosReturn<T, R, D> {
53+
export interface StrictUseAxiosReturn<T, R, D, O extends UseAxiosOptions = UseAxiosOptions<T>> extends UseAxiosReturn<T, R, D, O> {
5454
/**
5555
* Manually call the axios request
5656
*/
57-
execute: (url?: string | AxiosRequestConfig<D>, config?: AxiosRequestConfig<D>) => Promise<StrictUseAxiosReturn<T, R, D>>
57+
execute: (url?: string | AxiosRequestConfig<D>, config?: AxiosRequestConfig<D>) => Promise<StrictUseAxiosReturn<T, R, D, O>>
5858
}
5959
export interface EasyUseAxiosReturn<T, R, D> extends UseAxiosReturn<T, R, D> {
6060
/**
6161
* Manually call the axios request
6262
*/
6363
execute: (url: string, config?: AxiosRequestConfig<D>) => Promise<EasyUseAxiosReturn<T, R, D>>
6464
}
65-
export interface UseAxiosOptions<T = any> {
65+
export interface UseAxiosOptionsBase<T = any> {
6666
/**
6767
* Will automatically run axios request when `useAxios` is used
6868
*
@@ -93,11 +93,6 @@ export interface UseAxiosOptions<T = any> {
9393
*/
9494
onSuccess?: (data: T) => void
9595

96-
/**
97-
* Initial data to use
98-
*/
99-
initialData?: T
100-
10196
/**
10297
* Sets the state to initialState before executing the promise.
10398
*/
@@ -108,11 +103,24 @@ export interface UseAxiosOptions<T = any> {
108103
*/
109104
onFinish?: () => void
110105
}
106+
107+
export interface UseAxiosOptionsWithInitialData<T> extends UseAxiosOptionsBase<T> {
108+
/**
109+
* Initial data
110+
*/
111+
initialData: T
112+
}
113+
114+
export type UseAxiosOptions<T = any> = UseAxiosOptionsBase<T> | UseAxiosOptionsWithInitialData<T>
115+
111116
type OverallUseAxiosReturn<T, R, D> = StrictUseAxiosReturn<T, R, D> | EasyUseAxiosReturn<T, R, D>
112117

113-
export function useAxios<T = any, R = AxiosResponse<T>, D = any>(url: string, config?: AxiosRequestConfig<D>, options?: UseAxiosOptions): StrictUseAxiosReturn<T, R, D> & Promise<StrictUseAxiosReturn<T, R, D>>
114-
export function useAxios<T = any, R = AxiosResponse<T>, D = any>(url: string, instance?: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn<T, R, D> & Promise<StrictUseAxiosReturn<T, R, D>>
115-
export function useAxios<T = any, R = AxiosResponse<T>, D = any>(url: string, config: AxiosRequestConfig<D>, instance: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn<T, R, D> & Promise<StrictUseAxiosReturn<T, R, D>>
118+
export function useAxios<T = any, R = AxiosResponse<T>, D = any, O extends UseAxiosOptionsWithInitialData<T> = UseAxiosOptionsWithInitialData<T>>(url: string, config?: AxiosRequestConfig<D>, options?: O): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
119+
export function useAxios<T = any, R = AxiosResponse<T>, D = any, O extends UseAxiosOptionsWithInitialData<T> = UseAxiosOptionsWithInitialData<T>>(url: string, instance?: AxiosInstance, options?: O): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
120+
export function useAxios<T = any, R = AxiosResponse<T>, D = any, O extends UseAxiosOptionsWithInitialData<T> = UseAxiosOptionsWithInitialData<T>>(url: string, config: AxiosRequestConfig<D>, instance: AxiosInstance, options?: O): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
121+
export function useAxios<T = any, R = AxiosResponse<T>, D = any, O extends UseAxiosOptionsBase<T> = UseAxiosOptionsBase<T>>(url: string, config?: AxiosRequestConfig<D>, options?: O): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
122+
export function useAxios<T = any, R = AxiosResponse<T>, D = any, O extends UseAxiosOptionsBase<T> = UseAxiosOptionsBase<T>>(url: string, instance?: AxiosInstance, options?: O): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
123+
export function useAxios<T = any, R = AxiosResponse<T>, D = any, O extends UseAxiosOptionsBase<T> = UseAxiosOptionsBase<T>>(url: string, config: AxiosRequestConfig<D>, instance: AxiosInstance, options?: O): StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>
116124
export function useAxios<T = any, R = AxiosResponse<T>, D = any>(config?: AxiosRequestConfig<D>): EasyUseAxiosReturn<T, R, D> & Promise<EasyUseAxiosReturn<T, R, D>>
117125
export function useAxios<T = any, R = AxiosResponse<T>, D = any>(instance?: AxiosInstance): EasyUseAxiosReturn<T, R, D> & Promise<EasyUseAxiosReturn<T, R, D>>
118126
export function useAxios<T = any, R = AxiosResponse<T>, D = any>(config?: AxiosRequestConfig<D>, instance?: AxiosInstance): EasyUseAxiosReturn<T, R, D> & Promise<EasyUseAxiosReturn<T, R, D>>
@@ -160,14 +168,14 @@ export function useAxios<T = any, R = AxiosResponse<T>, D = any>(...args: any[])
160168
}
161169

162170
const {
163-
initialData,
164171
shallow,
165172
onSuccess = noop,
166173
onError = noop,
167174
immediate,
168175
resetOnExecute = false,
169176
} = options
170177

178+
const initialData = (options as UseAxiosOptionsWithInitialData<T>).initialData
171179
const response = shallowRef<AxiosResponse<T>>()
172180
const data = (shallow ? shallowRef : ref)<T>(initialData!) as Ref<T>
173181
const isFinished = ref(false)

0 commit comments

Comments
 (0)