我正在使用fp-ts,并且我有一个返回HttpError对象或字符串的函数:
async getPreferencesForUserId(userId: string): Promise<Either<HttpResponseNotFound, string>> {
const preferences = await getRepository(Preference).findOne({ userId });
return preferences ? right(preferences.preferenceMap) : left(new HttpResponseNotFound({ code: 404, message: 'Could not find preferences' }));
}
我想在另一个这样的文件中调用此函数:
const preferenceMapAsJsonStringOrError: Either<HttpResponseNotFound, string> = await this.preferenceService.getPreferencesForUserId(userId);
const response: HttpResponseOK | HttpResponseNotFound = pipe(preferenceMapAsJsonStringOrError, fold(
e => e,
r => new HttpResponseOK(r)
));
response.setHeader('content-type', 'application/json');
return response;
基本上,这就是我在Scala中要做的事情。 (除了fold
是Either类型的方法,不是独立函数-因此在这里,我使用的是pipe
帮助器)
问题是,我从ts-server收到错误消息:
Type 'HttpResponseOK' is missing the following properties from type 'HttpResponseNotFound': isHttpResponseNotFound, isHttpResponseClientError
和
node_modules/fp-ts/lib/Either.d.ts:129:69
129 export declare function fold<E, A, B>(onLeft: (e: E) => B, onRight: (a: A) => B): (ma: Either<E, A>) => B;
~~~~~~~~~~~
The expected type comes from the return type of this signature.
我可以通过更强制的方式解决此问题:
const preferenceMapAsJsonStringOrError: Either<HttpResponseNotFound, string> = await this.preferenceService.getPreferencesForUserId(userId);
if (isLeft(preferenceMapAsJsonStringOrError)) {
return preferenceMapAsJsonStringOrError.left;
}
const response = new HttpResponseOK(preferenceMapAsJsonStringOrError.right);
response.setHeader('content-type', 'application/json');
return response;
但是那时候我几乎失去了使用Either的好处。
答案 0 :(得分:1)
问题在于,考虑到TS推理的工作原理,使用fold
时,其返回类型将“固定”到第一个参数(onLeft
)和onRight
中的一个无法HttpResponseNotFound | HttpResponseOK
“扩展”它。
换句话说,在通常情况下,使用TS和fp-ts不会免费获得统一。
对于这种特定情况,我建议
type HttpResponse = HttpResponseNotFound | HttpResponseOK
onLeft
fold
参数的返回类型来手动完成此操作:const response: HttpResponse = pipe(
preferenceMapAsJsonStringOrError,
E.fold((e): HttpResponse => e, r => new HttpResponseOK(r))
)
或通过如下定义widen
助手:
const widen = E.mapLeft<HttpResponse, HttpResponse>(e => e);
const response: HttpResponse = pipe(
preferenceMapAsJsonStringOrError,
widen,
E.fold(identity, r => new HttpResponseOK(r))
);
希望这会有所帮助:)
答案 1 :(得分:0)
尝试2种方法后,我仍然收到类型错误。对我来说固定的是明确指定折叠的类型。
fold<HttpResponseNotFound, HttpResponseOK, HttpResponseNotFound | HttpResponseOK>(
e => e,
r => new HttpResponseOK(r)
)