providesTags does not work with callback when defining return type via TypeScript generic
shennan opened this issue · 4 comments
Prior Issues
Can't seem to find any
What is the current behavior?
With RTK Query, if using a providesTags
callback on a simple query while dictating return types/arguments with a generic, you receive a complicated TypeScript error:
Type '(result: PostId[] | undefined, error: FetchBaseQueryError | undefined, arg: void) => ("Post" | { type: string; id: string; })[]' is not assignable to type 'ResultDescription<"Post", PostId[], void, FetchBaseQueryError, FetchBaseQueryMeta | undefined> | undefined'.
Type '(result: PostId[] | undefined, error: FetchBaseQueryError | undefined, arg: void) => ("Post" | { type: string; id: string; })[]' is not assignable to type 'GetResultDescriptionFn<"Post", PostId[], void, FetchBaseQueryError, FetchBaseQueryMeta | undefined>'.
Type '("Post" | { type: string; id: string; })[]' is not assignable to type 'readonly TagDescription<"Post">[]'.
Type '"Post" | { type: string; id: string; }' is not assignable to type 'TagDescription<"Post">'.
Type '{ type: string; id: string; }' is not assignable to type 'TagDescription<"Post">'.
Type '{ type: string; id: string; }' is not assignable to type 'FullTagDescription<"Post">'.
Types of property 'type' are incompatible.
Type 'string' is not assignable to type '"Post"'.ts(2322)
endpointDefinitions.d.ts(223, 5): The expected type comes from property 'providesTags' which is declared here on type 'OmitFromUnion<QueryDefinition<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "Post", PostId[], "api">, "type">'
Steps to Reproduce
Try and define return type and params as generic for builder.query<any, any>
and TypeScript complains about your advanced providesTags
usage:
type Post = {
id: string
title: string
content: string
}
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseUrl: '/fakeApi' }),
tagTypes: ['Post'],
endpoints: builder => ({
getPosts: builder.query<Post[], void>({
query: () => '/posts',
providesTags: (result = [], error, arg) => [
'Post',
...result.map(({ id }) => ({ type: 'Post', id }))
]
}),
})
})
The above example is practically identical to the tutorial describing advanced RTK Query patterns (have shaved some endpoints to focus on the issue) and differs only that in my second code example I'm attempting to use a type and a generic to dictate the return type and arguments for the GET request.
Note
If I @ts-ignore
, things seem to work as expected.
What is the expected behavior?
There should be no TypeScript errors.
Environment Details
Version of Redux is v8.1.3. Not sure if this worked before.
try adding as const
to the type, i.e. result.map(({ id }) => ({ type: 'Post' as const, id }))
@EskiMojo14 Thanks. This appears to work, but can you explain why?
Sure - basically inside your map callback Typescript isn't aware that type
can only be a specific set of strings, it just infers that it's a string. Adding as const
means it becomes the literal type 'Post'
which matches the type requirements for tags.
Thanks for the explanation.