From 1789f1a2aeed3d2b5f828e0c140d2edf455dcecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Fiszer?= Date: Wed, 13 Nov 2019 00:50:27 +0100 Subject: [PATCH] Add types for react-query (#40312) * Add types for react-query * Add clearQueryCache export, fix typo in QueryOptions --- types/react-query/index.d.ts | 123 +++++++++++++++++++++++++ types/react-query/react-query-tests.ts | 66 +++++++++++++ types/react-query/tsconfig.json | 23 +++++ types/react-query/tslint.json | 1 + 4 files changed, 213 insertions(+) create mode 100644 types/react-query/index.d.ts create mode 100644 types/react-query/react-query-tests.ts create mode 100644 types/react-query/tsconfig.json create mode 100644 types/react-query/tslint.json diff --git a/types/react-query/index.d.ts b/types/react-query/index.d.ts new file mode 100644 index 0000000000..dede7f425b --- /dev/null +++ b/types/react-query/index.d.ts @@ -0,0 +1,123 @@ +// Type definitions for react-query 0.3 +// Project: https://github.com/tannerlinsley/react-query +// Definitions by: Lukasz Fiszer +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +import { ComponentType } from 'react'; + +export function useQuery( + queryKey: QueryKey, + queryFn: QueryFunction, + options?: QueryOptions +): QueryResult; + +export type QueryKey = string | [string, TVariables] | false | null | QueryKeyFunction; +export type QueryKeyFunction = () => string | [string, TVariables] | false | null; + +export type QueryFunction = (variables: TVariables) => Promise; + +export interface QueryOptions { + manual?: boolean; + paginated?: boolean; + getCanFetchMore?: (lastPage: number, allPages: number) => boolean; + retry?: boolean | number; + retryDelay?: (retryAttempt: number) => number; + staleTime?: number; + cacheTime?: number; + refetchInterval?: false | number; + onError?: (err: any) => void; + onSucess?: (data: TResult) => void; + suspense?: boolean; +} + +export interface QueryResult { + data: null | TResult; + error: null | Error; + isLoading: boolean; + isFetching: boolean; + isCached: boolean; + failureCount: number; + refetch: (arg?: {variables?: TVariables, merge?: (...args: any[]) => any, disableThrow?: boolean}) => void; + isFetchingMore: boolean; + canFetchMore: boolean; + fetchMore: (variables?: TVariables) => Promise; +} + +export function prefetchQuery( + queryKey: QueryKey, + queryFn: QueryFunction, + options?: PrefetchQueryOptions +): Promise; + +export interface PrefetchQueryOptions extends QueryOptions { + force?: boolean; +} + +export function useMutation( + mutationFn: MutationFunction, + mutationOptions?: MutationOptions +): [MutateFunction, MutationResult]; + +export type MutationFunction = ( + variables: TVariables, +) => Promise; + +export interface MutationOptions { + refetchQueries?: Array; + refetchQueriesOnFailure?: boolean; +} + +export type MutateFunction = ( + variables?: TVariables, + options?: { + updateQuery?: string | [string, object], + waitForRefetchQueries?: boolean; + } +) => Promise; + +export interface MutationResult { + data: TResults | null; + isLoading: boolean; + error: null | Error; + promise: Promise; +} + +export function setQueryData( + queryKey: string | [string, object], + data: any, + options?: { + shouldRefetch?: boolean + } +): void | Promise; + +export function refetchQuery( + queryKey: string | [string, object] | [string, false], + force?: { + force?: boolean + } +): Promise; + +export function refetchAllQueries( + options?: { + force?: boolean, + includeInactive: boolean + } +): Promise; + +export function useIsFetching(): boolean; + +export const ReactQueryConfigProvider: React.ComponentType<{ + config?: ReactQueryProviderConfig +}>; + +export interface ReactQueryProviderConfig { + retry: number; + retryDelay: (attempt: number) => number; + staleTime: number; + cacheTime: number; + refetchAllOnWindowFocus: boolean; + refetchInterval: boolean; + suspense: boolean; +} + +export function clearQueryCache(): void; diff --git a/types/react-query/react-query-tests.ts b/types/react-query/react-query-tests.ts new file mode 100644 index 0000000000..d35d8a0a0e --- /dev/null +++ b/types/react-query/react-query-tests.ts @@ -0,0 +1,66 @@ +import { useMutation, useQuery } from "react-query"; + +const queryFn = () => Promise.resolve(); + +// Query - simple case +const querySimple = useQuery('todos', + () => Promise.resolve('test')); +querySimple.data; // $ExpectType string | null +querySimple.error; // $ExpectType Error | null +querySimple.isLoading; // $ExpectType boolean +querySimple.refetch(); // $ExpectType void + +// Query Variables +const param = 'test'; +const queryVariables = useQuery(['todos', {param}], + (variables) => Promise.resolve(variables.param === 'test')); + +queryVariables.data; // $ExpectType boolean | null +queryVariables.refetch({variables: {param: 'foo'}}); // $ExpectType void +queryVariables.refetch({variables: {other: 'foo'}}); // $ExpectError + +// Query with falsey query key +useQuery(false && ['foo', { bar: 'baz' }], queryFn); + +// Query with query key function +useQuery(() => ['foo', { bar: 'baz' }], queryFn); + +// Query with nested variabes +const queryNested = useQuery(['key', { + nested: { + props: [1, 2] + } +}], (variables) => Promise.resolve(variables.nested.props[0])); +queryNested.data; // $ExpectType number | null + +// Simple mutation +const mutation = () => Promise.resolve(['foo', 1]); + +const [mutate] = useMutation(mutation, { + refetchQueries: ['todos', ['todo', { id: 5 }], 'reminders'], + refetchQueriesOnFailure: false +}); +mutate(); +mutate(undefined, { + updateQuery: 'query', + waitForRefetchQueries: false +}); + +// Invalid mutatation funciton +useMutation((arg1: string, arg2: string) => Promise.resolve()); // $ExpectError +useMutation((arg1: string) => null); // $ExpectError + +// Mutation with variables +const [mutateWithVars] = useMutation( + ({param}: {param: number}) => Promise.resolve(Boolean(param)), + { + refetchQueries: ['todos', ['todo', { id: 5 }], 'reminders'], + refetchQueriesOnFailure: false +}); + +mutateWithVars({param: 1}, { + updateQuery: 'query', + waitForRefetchQueries: false +}); + +mutateWithVars({param: 'test'}); // $ExpectError diff --git a/types/react-query/tsconfig.json b/types/react-query/tsconfig.json new file mode 100644 index 0000000000..f6399ec184 --- /dev/null +++ b/types/react-query/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "react-query-tests.ts" + ] +} diff --git a/types/react-query/tslint.json b/types/react-query/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/react-query/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }