目标
我们的目标是创建一个fetch函数,该函数将路径和方法作为参数,返回类型应该是由名为ScoresRoutes
的接口的相应response
属性定义的类型。
在ScoresRoutes
接口中,对象的顶级键可以是任何字符串--代表一个路由。每个键都应该是一个对象,它具有一组固定的字符串--即HTTP方法。最后,每个路由和方法组合都应该是一个对象,它总是具有response
属性。
行为
在下面代码的最后一行中,data
的类型 * 是 * 正确的类型--即使我向ScoresRoutes
接口添加了其他路由和方法--如果我尝试使用带有无效路由和方法对的customFetch
,TypeScript就会抛出错误。
但是,TypeScript仍然在函数定义中显示错误,称Type '"response"' cannot be used to index type 'ScoresRoutes[R][M]'
。
考虑到我拥有所需的功能,我可以将错误隐藏起来,但我认为该错误表明我的操作方式错误。
编号
这是我用来描述所需接口的一般形状的更广泛的类型:
type RequestMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE';
type GenericRoutes<Paths extends string> = {
[P in Paths]: {
[M in RequestMethod]?: {
request?: Record<string, unknown>,
response: Record<string, unknown> | null,
params?: Record<string, unknown>
}
}
}
那么下面我来具体实现一下:
type ScoresPath = '/';
interface ScoresRoutes extends GenericRoutes<ScoresPath> {
'/': {
'GET': {
response: {
test: true
}
}
}
}
最后,这是我创建的自定义fetch方法:
async function customFetch<
R extends ScoresPath,
M extends keyof ScoresRoutes[R]
>(
route: R,
method: M
): Promise<ScoresRoutes[R][M]['response']> { // This is where the TS error shows
const data = await fetch(route, { method: method as string }).then((res) => res.json());
return data;
}
customFetch('/', 'GET').then((data) => null); // `data` does have the proper type here
1条答案
按热度按时间gr8qqesn1#
我相信你得到这个错误是因为
response
字段可能实际上不存在。这是因为从ScoresRoutes[R][M]
返回的对象可能是未定义的。解决这个问题的一种方法是使用条件类型,它允许你在访问
response
属性之前检查你所得到的对象的类型。Playground链接