此bounty已结束。回答此问题可获得+150声望奖励。赏金宽限期9小时后结束。user1790300正在寻找一个答案从一个有信誉的来源。
我正在尝试使用typescript进行函数式编程,并将其用于一个新项目,但遇到了一些障碍。对于下面的代码,我正在使用它作为一个干净的架构模型,但收到了 typescript 错误,但不确定它告诉我问题在哪里。任何帮助了解我如何解决这个问题将不胜感激。
1.类型“TaskEither<Error,void>”不能分配给类型“TaskEither<Error,Option<User[]> Error”。
- 空虚从何而来,我又该如何修复它?
1.类型“的参数(国家/地区:string)=> TaskEither<Error,Option<User[]>>'不可分配给类型'(b:Either<DomainError,string>)=> TaskEither<Error,Option<User[]>返回“。参数“country”和“B”的类型不兼容。
- “B:<DomainError,string>”来自,我应该如何去修复它?
完整的错误消息列在代码部分下面。
import { pipe } from 'fp-ts/lib/function';
import { Option } from "fp-ts/Option";
import { some } from "fp-ts/Option";
import { Either } from 'fp-ts/lib/Either';
import * as E from 'fp-ts/lib/Either';
import { TaskEither, left, right, chain, fromEither } from 'fp-ts/lib/TaskEither';
type NotFoundError = { kind: string; message: string };
type DomainError = { kind: string, message: string };
type UserRepository = {
retrieveUsers: (page: number) => (name: string) => (street: string) => (city: string) => (state: string) => (zipCode: string) => (country: string) => TaskEither<Error, Option<User[]>>;
}
export const makeUserRepository = (client: Client): UserRepository => {
const retrieveUsers = (page) => (name) => (street) => (city) => (state) => (zipCode) => (country): TaskEither<Error, Option<User[]>> => tryCatch(
async () => {
let queryString = '';
let paramList = [];
let queryScenarios = [];
let counter = 0;
queryString += `
SELECT c."name", a."userId", a."companyId", a."city", a."state", a."zipCode", a."street", a."country"
FROM profile."User" a INNER JOIN profile."Company" c ON (a."companyId" = c."companyId")
`;
if (name && name.length > 0) {
queryScenarios.push('(c.name like %$' + (++counter) + '%)');
paramList.push(name);
}
if (street && street.length > 0) {
queryScenarios.push('a."street" like %$' + (++counter) + '%');
paramList.push(street);
}
if (city && city.length > 0) {
queryScenarios.push('a."city" like %$' + (++counter) + '%');
paramList.push(city);
}
if (state && state.length > 0) {
queryScenarios.push('a."state" like %$' + (++counter) + '%');
paramList.push(state);
}
if (zipCode && zipCode.length > 0) {
queryScenarios.push('a."zipCode" like %$' + (++counter) + '%');
paramList.push(zipCode);
}
if (country && country.length > 0) {
queryScenarios.push('a."country" like %$' + (++counter) + '%');
paramList.push(country);
}
queryString += " LIMIT $" + (++counter) + " OFFSET $" + (++counter);
paramList.push((isValidNumber(process.env.MAX_PAGE_SIZE) ? parseInt(process.env.MAX_PAGE_SIZE) : 0));
paramList.push((isValidNumber(process.env.MAX_PAGE_SIZE) ? parseInt(process.env.MAX_PAGE_SIZE) : 0) * (page - 1));
const result: QueryResult<User> = await client.query(queryString, paramList);
return result.rows.length > 0 ? some(result.rows) : none;
},
(reason) => new Error(String(reason))
);
return {
retrieveUsers
}
}
const validatePageNameFields = (page: number) => (name: string) => (street: string) => (city: string) => (state: string) => (zipCode: string) => (country: string): Either<DomainError, string> => {
const schema = Joi.object().keys({
name: Joi.string().min(4).max(50).allow(null),
page: Joi.number().required(),
street: Joi.string().min(8).max(75).allow(null),
city: Joi.string().min(1).max(50).allow(null),
state: Joi.string().min(1).max(50).allow(null),
zipCode: Joi.string().min(5).max(10).allow(null),
country: Joi.string().min(5).max(25).allow(null),
});
let {error} = schema.validateAsync({page, name, street, city, state, zipCode, country});
if (error && error.length > 0)
return E.left({ kind: 'ValidationError', message: error });
return E.right(country);
};
type UserInteractor = {
retrieveUserList: (page: number) => (name: string) => (street: string) => (city: string) => (state: string) => (zipCode: string) => (country: string) => TaskEither<Error | NotFoundError, Option<User[]>>;
};
export const makeUserInteractor = (repository: ReturnType<typeof makeUserRepository>): UserInteractor => {
const retrieveUserList = (page) => (name) => (street) => (city) => (state) => (zipCode) => (country): TaskEither<Error | NotFoundError, Option<User[]>> => {
return pipe(
country,
validatePageNameFields(page)(name)(street)(city)(state)(zipCode),
repository.retrieveUsers(page)(name)(street)(city)(state)(zipCode),
chain((maybeUser) => {
if (maybeUser._tag === 'None') {
return left({ kind: 'NotFoundError', message: 'User not found.' });
}
return right(some(maybeUser.value));
})
);
};
}
error TS2322: Type 'TaskEither<Error, void>' is not assignable to type 'TaskEither<Error, Option<User[]>>'.
Type 'void' is not assignable to type 'Option<User[]>'.
const retrieveUsers = (page) => (name) => (street) => (city) => (state) => (zipCode) => (country): TaskEither<Error, Option<User[]>> => tryCatch(
~~~~~~~~~
async () => {
~~~~~~~~~~~~~~~~~~~~~
...
(reason) => new Error(String(reason))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
);
~~~~~
error TS2345: Argument of type '(country: string) => TaskEither<Error, Option<User[]>>' is not assignable to parameter of type '(b: Either<DomainError, string>) => TaskEither<Error, Option<User[]>>'.
Types of parameters 'country' and 'b' are incompatible.
Type 'Either<DomainError, string>' is not assignable to type 'string'.
Type 'Right<string>' is not assignable to type 'string'.
repository.retrieveUsers(page)(name)(street)(city)(state)(zipCode),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1条答案
按热度按时间icnyk63a1#
我认为有以下几点需要改变