Home > Mobile >  How to type provideTags in redux-toolkit (many items endpoint)
How to type provideTags in redux-toolkit (many items endpoint)

Time:06-07

Following code works well, however I dont manage to type providesTags correctly:

type Post = {
  id: number,
  name: string,
  description: string,
}

const postsApiSlice = api.injectEndpoints({
    endpoints: (builder) => ({
      getPosts: builder.query<EntityState<Post>, void>({
        query: ROUTES.POSTS,
        transformResponse: (responseData: Post[]) => {
          return adapter.setAll(initialState, responseData)
        },
        // Typescript error is here, at provideTags
        providesTags: (result) => {
          // What to do if result is undefined?
          if (!result) return [{ type: POST_TAG, id: 'LIST' }]
  
          const tags = (result.ids.length > 0) ?
            // Typescript accepts type of next line if I return it
            result.ids.map((id) => ({ type: POST_TAG, id }))
            :
            // Typescript also accepts type of next line if I return it
            [{ type: POST_TAG, id: 'LIST' }]
          return tags
        }
      }),
    }),
  })

Typescript error I get:

Type '(result: EntityState<Post> | undefined) => { type: string; id: EntityId; }[]' is not assignable to type 'ResultDescription<"Post", EntityState<Post>, void, FetchBaseQueryError, {} | undefined> | undefined'.
  Type '(result: EntityState<Post> | undefined) => { type: string; id: EntityId; }[]' is not assignable to type 'GetResultDescriptionFn<"Post", EntityState<Post>, void, FetchBaseQueryError, {} | undefined>'.
    Type '{ type: string; id: EntityId; }[]' is not assignable to type 'readonly TagDescription<"Post">[]'.
      Type '{ type: string; id: EntityId; }' is not assignable to type 'TagDescription<"Post">'.
        Type '{ type: string; id: EntityId; }' 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(188, 5): The expected type comes from property 'providesTags' which is declared here on type 'Omit<EndpointDefinitionWithQuery<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, {}>, EntityState<Post>> & { ...; } & { ...; } & QueryExtraOptions<...>, "type"> | Omit<...>'

If I return just result.ids.map((id) => ({ type: POST_TAG, id })) or just [{ type: POST_TAG, id: 'LIST' }] works correctly.

  • How can I type it?
  • Also, not sure what should I do when result is undefined. Should I return [{ type: POST_TAG, id: 'LIST' }]?

CodePudding user response:

This is described in typing providesTag/invalidatesTags.

You will need a few as const assertions when you define POST_TAG.

So not const POST_TAG = "foo", but const POST_TAG = "foo" as const should do the trick. Otherwise it will be typed as "string", not as "foo".

  • Related