|
1 | 1 | import { describe, expectTypeOf, it } from 'vitest'
|
2 | 2 | import { QueryClient } from '../queryClient'
|
3 |
| -import type { QueryState } from '../query' |
4 |
| -import type { DataTag, InfiniteData, QueryKey } from '../types' |
| 3 | +import type { MutationFilters, QueryFilters, Updater } from '../utils' |
| 4 | +import type { Mutation } from '../mutation' |
| 5 | +import type { Query, QueryState } from '../query' |
| 6 | +import type { |
| 7 | + DataTag, |
| 8 | + DefaultError, |
| 9 | + DefaultedQueryObserverOptions, |
| 10 | + EnsureQueryDataOptions, |
| 11 | + FetchInfiniteQueryOptions, |
| 12 | + InfiniteData, |
| 13 | + MutationOptions, |
| 14 | + OmitKeyof, |
| 15 | + QueryKey, |
| 16 | + QueryObserverOptions, |
| 17 | +} from '../types' |
5 | 18 |
|
6 | 19 | describe('getQueryData', () => {
|
7 | 20 | it('should be typed if key is tagged', () => {
|
@@ -184,3 +197,307 @@ describe('defaultOptions', () => {
|
184 | 197 | })
|
185 | 198 | })
|
186 | 199 | })
|
| 200 | + |
| 201 | +describe('fully typed usage', () => { |
| 202 | + it('type-checks various methods with data & error included in the type', async () => { |
| 203 | + const queryClient = new QueryClient() |
| 204 | + |
| 205 | + type TData = { foo: string } |
| 206 | + type TError = DefaultError & { bar: string } |
| 207 | + |
| 208 | + // |
| 209 | + // Construct typed arguments |
| 210 | + // |
| 211 | + |
| 212 | + const queryOptions: EnsureQueryDataOptions<TData, TError> = { |
| 213 | + queryKey: ['key'] as any, |
| 214 | + } |
| 215 | + const fetchInfiniteQueryOptions: FetchInfiniteQueryOptions<TData, TError> = |
| 216 | + { |
| 217 | + queryKey: ['key'] as any, |
| 218 | + pages: 5, |
| 219 | + getNextPageParam: (lastPage) => { |
| 220 | + expectTypeOf(lastPage).toEqualTypeOf<TData>() |
| 221 | + return 0 |
| 222 | + }, |
| 223 | + initialPageParam: 0, |
| 224 | + } |
| 225 | + const mutationOptions: MutationOptions<TData, TError> = {} |
| 226 | + |
| 227 | + const queryFilters: QueryFilters< |
| 228 | + TData, |
| 229 | + TError, |
| 230 | + TData, |
| 231 | + QueryKey & DataTag<unknown, TData, TError> |
| 232 | + > = { |
| 233 | + predicate(query) { |
| 234 | + expectTypeOf(query).toEqualTypeOf< |
| 235 | + Query< |
| 236 | + TData, |
| 237 | + TError, |
| 238 | + TData, |
| 239 | + QueryKey & DataTag<unknown, TData, TError> |
| 240 | + > |
| 241 | + >() |
| 242 | + expectTypeOf(query.state.data).toEqualTypeOf<TData | undefined>() |
| 243 | + expectTypeOf(query.state.error).toEqualTypeOf<TError | null>() |
| 244 | + return false |
| 245 | + }, |
| 246 | + } |
| 247 | + const queryKey = queryFilters.queryKey! |
| 248 | + |
| 249 | + const mutationFilters: MutationFilters<TData, TError> = { |
| 250 | + predicate(mutation) { |
| 251 | + expectTypeOf(mutation).toEqualTypeOf<Mutation<TData, TError>>() |
| 252 | + expectTypeOf(mutation.state.data).toEqualTypeOf<TData | undefined>() |
| 253 | + expectTypeOf(mutation.state.error).toEqualTypeOf<TError | null>() |
| 254 | + return false |
| 255 | + }, |
| 256 | + } |
| 257 | + const mutationKey = mutationOptions.mutationKey! |
| 258 | + |
| 259 | + // |
| 260 | + // Method type tests |
| 261 | + // |
| 262 | + |
| 263 | + const state = queryClient.getQueryState(queryKey) |
| 264 | + expectTypeOf(state).toEqualTypeOf<QueryState<TData, TError> | undefined>() |
| 265 | + |
| 266 | + const queryData1 = queryClient.getQueryData(queryKey) |
| 267 | + expectTypeOf(queryData1).toEqualTypeOf<TData | undefined>() |
| 268 | + |
| 269 | + const queryData2 = await queryClient.ensureQueryData(queryOptions) |
| 270 | + expectTypeOf(queryData2).toEqualTypeOf<TData>() |
| 271 | + |
| 272 | + const queriesData = queryClient.getQueriesData(queryFilters) |
| 273 | + expectTypeOf(queriesData).toEqualTypeOf< |
| 274 | + Array<[QueryKey, TData | undefined]> |
| 275 | + >() |
| 276 | + |
| 277 | + const queryData3 = queryClient.setQueryData(queryKey, { foo: '' }) |
| 278 | + type SetQueryDataUpdaterArg = Parameters< |
| 279 | + typeof queryClient.setQueryData<unknown, typeof queryKey> |
| 280 | + >[1] |
| 281 | + |
| 282 | + expectTypeOf<SetQueryDataUpdaterArg>().toEqualTypeOf< |
| 283 | + Updater<TData | undefined, TData | undefined> |
| 284 | + >() |
| 285 | + expectTypeOf(queryData3).toEqualTypeOf<TData | undefined>() |
| 286 | + |
| 287 | + const queriesData2 = queryClient.setQueriesData(queryFilters, { foo: '' }) // TODO: types here are wrong and coming up undefined |
| 288 | + type SetQueriesDataUpdaterArg = Parameters< |
| 289 | + typeof queryClient.setQueriesData<unknown, typeof queryFilters> |
| 290 | + >[1] |
| 291 | + |
| 292 | + expectTypeOf<SetQueriesDataUpdaterArg>().toEqualTypeOf< |
| 293 | + Updater<TData | undefined, TData | undefined> |
| 294 | + >() |
| 295 | + expectTypeOf(queriesData2).toEqualTypeOf< |
| 296 | + Array<[QueryKey, TData | undefined]> |
| 297 | + >() |
| 298 | + |
| 299 | + const queryState = queryClient.getQueryState(queryKey) |
| 300 | + expectTypeOf(queryState).toEqualTypeOf< |
| 301 | + QueryState<TData, TError> | undefined |
| 302 | + >() |
| 303 | + |
| 304 | + const fetchedQuery = await queryClient.fetchQuery(queryOptions) |
| 305 | + expectTypeOf(fetchedQuery).toEqualTypeOf<TData>() |
| 306 | + |
| 307 | + queryClient.prefetchQuery(queryOptions) |
| 308 | + |
| 309 | + const infiniteQuery = await queryClient.fetchInfiniteQuery( |
| 310 | + fetchInfiniteQueryOptions, |
| 311 | + ) |
| 312 | + expectTypeOf(infiniteQuery).toEqualTypeOf<InfiniteData<TData, unknown>>() |
| 313 | + |
| 314 | + const infiniteQueryData = await queryClient.ensureInfiniteQueryData( |
| 315 | + fetchInfiniteQueryOptions, |
| 316 | + ) |
| 317 | + expectTypeOf(infiniteQueryData).toEqualTypeOf< |
| 318 | + InfiniteData<TData, unknown> |
| 319 | + >() |
| 320 | + |
| 321 | + const defaultQueryOptions = queryClient.defaultQueryOptions(queryOptions) |
| 322 | + expectTypeOf(defaultQueryOptions).toEqualTypeOf< |
| 323 | + DefaultedQueryObserverOptions<TData, TError, TData, TData, QueryKey> |
| 324 | + >() |
| 325 | + |
| 326 | + const mutationOptions2 = queryClient.defaultMutationOptions(mutationOptions) |
| 327 | + expectTypeOf(mutationOptions2).toEqualTypeOf< |
| 328 | + MutationOptions<TData, TError, void, unknown> |
| 329 | + >() |
| 330 | + |
| 331 | + queryClient.setMutationDefaults(mutationKey, { |
| 332 | + onSettled(data, error, variables, context) { |
| 333 | + expectTypeOf(data).toEqualTypeOf<unknown>() |
| 334 | + expectTypeOf(error).toEqualTypeOf<DefaultError | null>() |
| 335 | + expectTypeOf(variables).toEqualTypeOf<void>() |
| 336 | + expectTypeOf(context).toEqualTypeOf<unknown>() |
| 337 | + }, |
| 338 | + }) |
| 339 | + |
| 340 | + const queryDefaults = queryClient.getQueryDefaults(queryKey) |
| 341 | + expectTypeOf(queryDefaults).toEqualTypeOf< |
| 342 | + OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'> |
| 343 | + >() |
| 344 | + |
| 345 | + // Voids and Untyped returns |
| 346 | + queryClient.invalidateQueries(queryFilters) |
| 347 | + queryClient.isFetching(queryFilters) |
| 348 | + queryClient.isMutating(mutationFilters) |
| 349 | + queryClient.removeQueries(queryFilters) |
| 350 | + queryClient.resetQueries(queryFilters) |
| 351 | + queryClient.cancelQueries(queryFilters) |
| 352 | + queryClient.invalidateQueries(queryFilters) |
| 353 | + queryClient.refetchQueries(queryFilters) |
| 354 | + queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions) |
| 355 | + queryClient.setQueryDefaults(queryKey, {} as any) |
| 356 | + queryClient.getMutationDefaults(mutationKey) |
| 357 | + }) |
| 358 | + |
| 359 | + it('type-checks various methods with untyped arguments', async () => { |
| 360 | + const queryClient = new QueryClient() |
| 361 | + |
| 362 | + // |
| 363 | + // Construct typed arguments |
| 364 | + // |
| 365 | + |
| 366 | + const queryOptions: EnsureQueryDataOptions = { |
| 367 | + queryKey: ['key'] as any, |
| 368 | + } |
| 369 | + const fetchInfiniteQueryOptions: FetchInfiniteQueryOptions = { |
| 370 | + queryKey: ['key'] as any, |
| 371 | + pages: 5, |
| 372 | + getNextPageParam: (lastPage) => { |
| 373 | + expectTypeOf(lastPage).toEqualTypeOf<unknown>() |
| 374 | + return 0 |
| 375 | + }, |
| 376 | + initialPageParam: 0, |
| 377 | + } |
| 378 | + const mutationOptions: MutationOptions = {} |
| 379 | + |
| 380 | + const queryFilters: QueryFilters = { |
| 381 | + predicate(query) { |
| 382 | + expectTypeOf(query).toEqualTypeOf<Query<unknown, DefaultError>>() |
| 383 | + expectTypeOf(query.state.data).toEqualTypeOf<unknown>() |
| 384 | + expectTypeOf(query.state.error).toEqualTypeOf<DefaultError | null>() |
| 385 | + return false |
| 386 | + }, |
| 387 | + } |
| 388 | + const queryKey = queryFilters.queryKey! |
| 389 | + |
| 390 | + const mutationFilters: MutationFilters = { |
| 391 | + predicate(mutation) { |
| 392 | + expectTypeOf(mutation).toEqualTypeOf<Mutation>() |
| 393 | + expectTypeOf(mutation.state.data).toEqualTypeOf<unknown>() |
| 394 | + expectTypeOf(mutation.state.error).toEqualTypeOf<DefaultError | null>() |
| 395 | + return false |
| 396 | + }, |
| 397 | + } |
| 398 | + const mutationKey = mutationOptions.mutationKey! |
| 399 | + |
| 400 | + // |
| 401 | + // Method type tests |
| 402 | + // |
| 403 | + |
| 404 | + const state = queryClient.getQueryState(queryKey) |
| 405 | + expectTypeOf(state).toEqualTypeOf< |
| 406 | + QueryState<unknown, DefaultError> | undefined |
| 407 | + >() |
| 408 | + |
| 409 | + const queryData1 = queryClient.getQueryData(queryKey) |
| 410 | + expectTypeOf(queryData1).toEqualTypeOf<unknown>() |
| 411 | + |
| 412 | + const queryData2 = await queryClient.ensureQueryData(queryOptions) |
| 413 | + expectTypeOf(queryData2).toEqualTypeOf<unknown>() |
| 414 | + |
| 415 | + const queriesData = queryClient.getQueriesData(queryFilters) |
| 416 | + expectTypeOf(queriesData).toEqualTypeOf<Array<[QueryKey, unknown]>>() |
| 417 | + |
| 418 | + const queryData3 = queryClient.setQueryData(queryKey, { foo: '' }) |
| 419 | + type SetQueryDataUpdaterArg = Parameters< |
| 420 | + typeof queryClient.setQueryData<unknown, typeof queryKey> |
| 421 | + >[1] |
| 422 | + |
| 423 | + expectTypeOf<SetQueryDataUpdaterArg>().toEqualTypeOf< |
| 424 | + Updater<unknown, unknown> |
| 425 | + >() |
| 426 | + expectTypeOf(queryData3).toEqualTypeOf<unknown>() |
| 427 | + |
| 428 | + const queriesData2 = queryClient.setQueriesData(queryFilters, { foo: '' }) // TODO: types here are wrong and coming up undefined |
| 429 | + type SetQueriesDataUpdaterArg = Parameters< |
| 430 | + typeof queryClient.setQueriesData<unknown, typeof queryFilters> |
| 431 | + >[1] |
| 432 | + |
| 433 | + expectTypeOf<SetQueriesDataUpdaterArg>().toEqualTypeOf< |
| 434 | + Updater<unknown, unknown> |
| 435 | + >() |
| 436 | + expectTypeOf(queriesData2).toEqualTypeOf<Array<[QueryKey, unknown]>>() |
| 437 | + |
| 438 | + const queryState = queryClient.getQueryState(queryKey) |
| 439 | + expectTypeOf(queryState).toEqualTypeOf< |
| 440 | + QueryState<unknown, DefaultError> | undefined |
| 441 | + >() |
| 442 | + |
| 443 | + const fetchedQuery = await queryClient.fetchQuery(queryOptions) |
| 444 | + expectTypeOf(fetchedQuery).toEqualTypeOf<unknown>() |
| 445 | + |
| 446 | + queryClient.prefetchQuery(queryOptions) |
| 447 | + |
| 448 | + const infiniteQuery = await queryClient.fetchInfiniteQuery( |
| 449 | + fetchInfiniteQueryOptions, |
| 450 | + ) |
| 451 | + expectTypeOf(infiniteQuery).toEqualTypeOf<InfiniteData<unknown, unknown>>() |
| 452 | + |
| 453 | + const infiniteQueryData = await queryClient.ensureInfiniteQueryData( |
| 454 | + fetchInfiniteQueryOptions, |
| 455 | + ) |
| 456 | + expectTypeOf(infiniteQueryData).toEqualTypeOf< |
| 457 | + InfiniteData<unknown, unknown> |
| 458 | + >() |
| 459 | + |
| 460 | + const defaultQueryOptions = queryClient.defaultQueryOptions(queryOptions) |
| 461 | + expectTypeOf(defaultQueryOptions).toEqualTypeOf< |
| 462 | + DefaultedQueryObserverOptions< |
| 463 | + unknown, |
| 464 | + DefaultError, |
| 465 | + unknown, |
| 466 | + unknown, |
| 467 | + QueryKey |
| 468 | + > |
| 469 | + >() |
| 470 | + |
| 471 | + const mutationOptions2 = queryClient.defaultMutationOptions(mutationOptions) |
| 472 | + expectTypeOf(mutationOptions2).toEqualTypeOf< |
| 473 | + MutationOptions<unknown, DefaultError, void, unknown> |
| 474 | + >() |
| 475 | + |
| 476 | + queryClient.setMutationDefaults(mutationKey, { |
| 477 | + onSettled(data, error, variables, context) { |
| 478 | + expectTypeOf(data).toEqualTypeOf<unknown>() |
| 479 | + expectTypeOf(error).toEqualTypeOf<DefaultError | null>() |
| 480 | + expectTypeOf(variables).toEqualTypeOf<void>() |
| 481 | + expectTypeOf(context).toEqualTypeOf<unknown>() |
| 482 | + }, |
| 483 | + }) |
| 484 | + |
| 485 | + const queryDefaults = queryClient.getQueryDefaults(queryKey) |
| 486 | + expectTypeOf(queryDefaults).toEqualTypeOf< |
| 487 | + OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'> |
| 488 | + >() |
| 489 | + |
| 490 | + // Voids and Untyped returns |
| 491 | + queryClient.invalidateQueries(queryFilters) |
| 492 | + queryClient.isFetching(queryFilters) |
| 493 | + queryClient.isMutating(mutationFilters) |
| 494 | + queryClient.removeQueries(queryFilters) |
| 495 | + queryClient.resetQueries(queryFilters) |
| 496 | + queryClient.cancelQueries(queryFilters) |
| 497 | + queryClient.invalidateQueries(queryFilters) |
| 498 | + queryClient.refetchQueries(queryFilters) |
| 499 | + queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions) |
| 500 | + queryClient.setQueryDefaults(queryKey, {} as any) |
| 501 | + queryClient.getMutationDefaults(mutationKey) |
| 502 | + }) |
| 503 | +}) |
0 commit comments