我为我的Http模块创建了以下类型:
export type HttpPromise<TData> = Promise<HttpPromiseSuccess<TData>>
export type HttpPromiseSuccess<TData> = {
config: object;
headers: object;
request: XMLHttpRequest;
status: number;
statusText: string;
data: TData;
}
假设我有以下两种类型:
export type User = {
id: number;
name: string;
...
}
export type ApiError = {
error: string;
statusCode: number;
}
我通常会这样做:
const promise: HttpPromise<User> = Http.get('/api/users/1');
promise
.then(response => {
// response.data is now of type `User`
});
但我的API实际上可以返回错误类型ApiError
,因此我希望response.data
属于User
类型或ApiError
类型。我试过了
const promise: HttpPromise<User | ApiError> = Http.get('/api/users/1');
// But now response.data only contains the union of the two type
我也试过
const promise: HttpPromise<User> = Http.get('/api/users/1');
promise
.then(response => {
if ('error' in response.data) {
const payload = response.data as ApiError;
}
});
但这不能做铸造。我有什么选择?不幸的是我无法控制API; API将始终返回200
,但如果有效内容包含error
,那么它将包含包含代码的statusCode
。
答案 0 :(得分:2)
您可以使用user defined typeguard。
打字机本身如下:
const isError = <T>(response: T | ApiError): response is ApiError => {
return !!(response as ApiError).data.error;
};
这将返回一个布尔值 - 如果响应是错误则为true,否则返回false。您的请求处理程序可以是:
const promise: HttpPromise<User | ApiError> = Http.get('/api/users/1');
promise
.then(response => {
if (isError(response)) {
// response typed as ApiError
} else {
// response typed as User
}
});
因为typeguard是通用的,所以这也适用于其他响应类型:
const promise: HttpPromise<BlogPost | ApiError> = Http.get('/api/users/1');
promise
.then(response => {
if (isError(response)) {
// response typed as ApiError
} else {
// response typed as BlogPost
}
});