typescript - 是否可以拆分泛型类型?
问题描述
我调用的 API 端点以以下形式提供数据:
interface ArrayResponse<T> {
data: Partial<T>[]
}
interface ObjectResponse<T> {
data: Partial<T>
}
我编写了一个调用端点并返回响应的函数:
function fetchOne<T>(path: string): ObjectResponse<T> {
// HTTP call
}
function fetchMany<T>(path: string): ArrayResponse<T> {
// Exact same HTTP logic as above
}
理想情况下,我希望有一个单一的响应类型:
interface Response<T> {
data: Partial<T> | Partial<T>[]
}
但我真正想要的是能够让上述类型根据传递给 T 的值来确定 Partial 或 Partial[]。
所以Response<T>
会导致data: Partial<T>
和Response<T>[]
结果data: Partial<T>[]
。
我也对达到相同效果的其他创造性方法持开放态度。
解决方案
您可以使用用户定义的类型防护来做到这一点
所以,如果你有这些接口:
interface ObjectResponse<T> {
data: Partial<T>
}
interface ArrayResponse<T> {
data: Partial<T>[]
}
type IResponse<T> = ObjectResponse<T> | ArrayResponse<T>;
您可以编写此保护函数:
function isMultiResponse<T>(response: IResponse<T>): response is ArrayResponse<T> {
return Array.isArray(response.data);
}
此函数将获取 类型IResponse<T>
,并确定它是否为ArrayResponse<T>
. 这将允许您在运行时检查它是哪种类型。
这转换为常规 javascript,但 typescript 知道此函数确定类型。
因此,对于您的两个功能,如果逻辑相同,您可以将它们组合起来:
async function fetchData<T>(path: string): Promise<IResponse<T>> {
// HTTP call
return get(path);
}
并且当你使用用户定义的保护函数时,typescript 会知道响应是哪种类型:
async function doSomething<T>(): Promise<void> {
const path = '';
const res: IResponse<T> = await fetchData(path);
if (isMultiResponse(res)) {
// typescript will know the response is ArrayResponse<T>
console.log(res.data[0]);
} else {
// typescript will know the response is ObjectResponse<T>
console.log(res.data);
}
}
VS 代码在行动
编译代码
当编译成 JavaScript 时,isMultiResponse
函数和 if 语句显然会在那里。但是你可能想要在你的代码中的某个地方进行这样的检查 :-) 使用Type Guard编写它会在运行时进行必要的检查,但也会让 typescript 知道这两种不同的场景并相应地给你反馈。
推荐阅读
- mongodb - Spring Boot MongoDB 连接问题
- java - 每当我选择任何单选按钮时,它都会自动选择最后一个,我该怎么办?
- c++ - unordered_map 迭代器指向 end(),如何从 unordered_map 中检索键?
- reactjs - react-leaflet 记住缩放和中心位置
- c++ - 位置没有在事件c ++中更新
- angular - 从AngularJS中的任何其他组件调用时更改模态调用按钮的文本
- etl - 在 NiFi 中加入三个具有不同标题的 csv 文件
- spring-boot - 如何通过 JWT 令牌限制用户查看/编辑记录?
- python - 在 Python 中给出不同结果的基本操作
- javascript - Express Router 导致 XHR onreadystate 3