NodeJS 功能型脚本错误消息帮助清洁架构项目

qgzx9mmu  于 12个月前  发布在  Node.js
关注(0)|答案(1)|浏览(121)

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),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
icnyk63a

icnyk63a1#

我认为有以下几点需要改变

  1. retrieveUsers函数返回void而不是Option<User[]>。这是因为tryCatch函数没有返回值2。validatePageNameFields函数返回Either<DomainError,string>而不是string
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))
);

const validatePageNameFields = async (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} = await 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);
};

相关问题