与 TypeScript 一起使用
你将学到什么
- 如何使用各种 RTK Query APIs 与 TypeScript
简介
与 Redux Toolkit 包的其余部分一样,RTK Query 是用 TypeScript 编写的,其 API 旨在在 TypeScript 应用程序中无缝使用。
此页面提供了使用 RTK Query 中包含的 APIs 与 TypeScript 以及如何正确地对它们进行类型化的详细信息。
信息
我们强烈建议使用 TypeScript 4.1+ 与 RTK Query 以获得最佳结果。
如果你遇到任何在此页面上未描述的类型问题,请开启一个问题进行讨论。
createApi
使用自动生成的 React 钩子
RTK Query 的 React 特定入口点导出了一个版本的 createApi
,它会自动为定义的查询和突变 endpoints
生成 React 钩子。
要作为 TypeScript 用户使用自动生成的 React 钩子,你需要使用 TS4.1+。
// 文件: src/services/types.ts noEmit
export type Pokemon = {}
// 文件: src/services/pokemon.ts
// 需要使用 React 特定的入口点以允许生成 React 钩子
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import type { Pokemon } from './types'
// 使用基础 URL 和预期的端点定义服务
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
}),
}),
})
// 导出用于在函数组件中使用的钩子,这些钩子是
// 根据定义的端点自动生成的
export const { useGetPokemonByNameQuery } = pokemonApi
对于旧版本的 TS,你可以使用 api.endpoints.[endpointName].useQuery/useMutation
来访问相同的钩子。
直接访问 api 钩子
// 文件: src/services/types.ts noEmit
export type Pokemon = {}
// 文件: src/services/pokemon.ts noEmit
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import type { Pokemon } from './types'
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
}),
}),
})
export const { useGetPokemonByNameQuery } = pokemonApi
// 文件: src/services/manual-query.ts
import { pokemonApi } from './pokemon'
const useGetPokemonByNameQuery = pokemonApi.endpoints.getPokemonByName.useQuery
对 baseQuery
进行类型化
可以使用 RTK Query 导出的 BaseQueryFn
类型对自定义 baseQuery
进行类型化。
Base Query 签名
export type BaseQueryFn<
Args = any,
Result = unknown,
Error = unknown,
DefinitionExtraOptions = {},
Meta = {},
> = (
args: Args,
api: BaseQueryApi,
extraOptions: DefinitionExtraOptions,
) => MaybePromise<QueryReturnValue<Result, Error, Meta>>
export interface BaseQueryApi {
signal: AbortSignal
dispatch: ThunkDispatch<any, any, any>
getState: () => unknown
}
export type QueryReturnValue<T = unknown, E = unknown, M = unknown> =
| {
error: E
data?: undefined
meta?: M
}
| {
error?: undefined
data: T
meta?: M
}
BaseQueryFn
类型接受以下泛型:
Args
- 函数的第一个参数的类型。端点上的query
属性返回的结果将在此处传递。Result
- 成功情况下data
属性要返回的类型。除非你期望所有查询和突变都返回相同的类型,否则建议将此类型保持为unknown
,并如下所示单独指定类型。Error
- 错误情况下error
属性要返回的类型。此类型也适用于 API 定义中所有端点使用的queryFn
函数。DefinitionExtraOptions
- 函数的第三个参数的类型。在端点上提供给extraOptions
属性的值将在此处传递。Meta
- 可能从调用baseQuery
返回的meta
属性的类型。meta
属性可以作为transformResponse
和transformErrorResponse
的第二个参数访问。
备注
从 baseQuery
返回的 meta
属性总是被视为可能未定义的,因为在错误情况下可能会导致它未被提供。在访问 meta
属性的值时,应考虑到这一点,例如使用可选链。
简单的 baseQuery TypeScript 示例
import { createApi } from '@reduxjs/toolkit/query'
import type { BaseQueryFn } from '@reduxjs/toolkit/query'
const simpleBaseQuery: BaseQueryFn<
string, // Args
unknown, // Result
{ reason: string }, // Error
{ shout?: boolean }, // DefinitionExtraOptions
{ timestamp: number } // Meta
> = (arg, api, extraOptions) => {
// `arg` 的类型为 `string`
// `api` 的类型为 `BaseQueryApi`(不可配置)
// `extraOptions` 的类型为 `{ shout?: boolean }
const meta = { timestamp: Date.now() }
if (arg === 'forceFail') {
return {
error: {
reason: 'Intentionally requested to fail!',
meta,
},
}
}
if (extraOptions.shout) {
return { data: 'CONGRATULATIONS', meta }
}
return { data: 'congratulations', meta }
}
const api = createApi({
baseQuery: simpleBaseQuery,
endpoints: (builder) => ({
getSupport: builder.query({
query: () => 'support me',
extraOptions: {
shout: true,
},
}),
}),
})