使用管道函数时,typescript fp-ts 代码出现类型错误

问题描述 投票:0回答:1

我尝试使用 fp-ts 函数编程库编写代码,但不断收到以下类型错误:

TS2322:类型未知不可分配给类型 TaskEither 任务要么。 d. ts(1340, 42):期望的类型来自该签名的返回类型。

  1. 问题是什么,因为我不确定错误告诉我问题是什么?

  2. 如何修复此错误?

任何帮助将不胜感激。

下面代码中突出显示的部分似乎是错误的来源:

const findByUserAndGroup = groupMemberRepository.findByUserAndGroup(cancelGroupMembershipDTO.groupId);

pipe(
    sequenceS(ApplyPar)({
        user: findByUserAndGroup(cancelGroupMembershipDTO.userId),
        userToCancel: findByUserAndGroup(cancelGroupMembershipDTO.userToCancelId)
    }),
    chain(({ user, userToCancel }) =>
        **pipe(
            user,
            isGroupOwner,
            fromEither,
            map(() => userToCancel)
        )**
    ),
    map((userToCancel) => ({
        groupMemberId: userToCancel.groupMemberId,
        groupId: userToCancel.groupId,
        userId: userToCancel.userId,
        isGroupOwner: userToCancel.isGroupOwner
    })),
    chain((processedDetails) => userRepo.delete(processedDetails))
)

按用户和组查找:

const findByUserAndGroup = (groupMemberId: string) => (userId: string): TaskEither<ErrorBase, Option<GroupMember>> => {
    return pipe(
        tryCatch(
            () => pool.query(
                `select *
                from groupMember
                where groupMemberId = ${groupMemberId} and userId = ${userId}
                `
            ),
            (error: any) => ({message: `Database error: ${String(error)}`, name: 'SystemError', details: 'Database Error.', innerError: error})
        ),
        chain(result => right(none))
    );
}

IsGroupOwner 验证函数:

export const isGroupOwner = (groupMember: GroupMember): TaskEither<ErrorBase, GroupMember> => {
    if (!groupMember.isGroupOwner) {
        return left({message: `You do not have the permissions necessary to perform this operation.`)});
    }

    return right(groupMember);
}
node.js typescript functional-programming fp-ts
1个回答
0
投票

错误消息 Typeknown is not allocate to type

TaskEither<ErrorBase, unknown>
表明 TypeScript 期望特定的返回类型 (
TaskEither<ErrorBase, unknown>
),但它却接收到未知的类型。

代码中的罪魁祸首很可能是由于

findByUserAndGroup
返回的 Option 类型造成的。当您从
findByUserAndGroup
返回包装在 TaskEither 中的 Option 时,它与您正在使用的功能链中的预期类型不直接匹配。当类型通过管道和链传递时,这种差异会导致问题。

要解决此问题,您需要正确处理 Option 类型,将其转换为

TaskEither
。以下是调整代码的方法:

  • 正确处理选项类型:当

    findByUserAndGroup
    返回选项时,您应该将其映射到管道内的Either。如果Option为None,则返回错误(使用
    fp-ts
    中的left);否则,继续使用
    Some
    值。

  • 重构管道:您应该确保

    isGroupOwner
    接收到
    GroupMember
    并且所有返回的类型都对齐为
    TaskEither<ErrorBase, GroupMember
    >。

  • 修改 isGroupOwner 用法:使用

    fromOption
    Option<GroupMember>
    转换为管道内的
    Either
    。这将确保您在整个过程中获得一致的输入。


import { TaskEither, chain, map, left, right, fromEither } from 'fp-ts/TaskEither';
import { Option, fold as foldOption, some, none } from 'fp-ts/Option';
import { pipe } from 'fp-ts/function';
import { sequenceS } from 'fp-ts/Apply';
import { ApplyPar } from 'fp-ts/TaskEither';
import { fromOption } from 'fp-ts/Either';
import { ErrorBase } from './types'; // Assuming you have this type defined elsewhere

// Adjusted `findByUserAndGroup` function to match the expected types
const findByUserAndGroup = (groupMemberId: string) => (userId: string): TaskEither<ErrorBase, GroupMember> => {
    return pipe(
        tryCatch(
            () => pool.query(
                `select *
                from groupMember
                where groupMemberId = ${groupMemberId} and userId = ${userId}
                `
            ),
            (error: any) => ({ message: `Database error: ${String(error)}`, name: 'SystemError', details: 'Database Error.', innerError: error })
        ),
        chain(result => {
            // Assuming your query result parsing here to Option
            const groupMemberOption = some(result.rows[0]); // Replace with actual parsing logic
            return fromOption(() => ({ message: "Group member not found", name: "NotFoundError" }))(groupMemberOption);
        })
    );
};

// The `isGroupOwner` function remains the same
export const isGroupOwner = (groupMember: GroupMember): TaskEither<ErrorBase, GroupMember> => {
    if (!groupMember.isGroupOwner) {
        return left({ message: `You do not have the permissions necessary to perform this operation.` });
    }
    return right(groupMember);
};

// Main pipe function
const result = pipe(
    sequenceS(ApplyPar)({
        user: findByUserAndGroup(cancelGroupMembershipDTO.groupId)(cancelGroupMembershipDTO.userId),
        userToCancel: findByUserAndGroup(cancelGroupMembershipDTO.groupId)(cancelGroupMembershipDTO.userToCancelId)
    }),
    chain(({ user, userToCancel }) =>
        pipe(
            user,
            fromEither(() => ({ message: 'User not found', name: 'NotFoundError' })), // Convert `Option` to `Either`
            chain(isGroupOwner), // Now `isGroupOwner` will work on `GroupMember`
            map(() => userToCancel)
        )
    ),
    map((userToCancel) => ({
        groupMemberId: userToCancel.groupMemberId,
        groupId: userToCancel.groupId,
        userId: userToCancel.userId,
        isGroupOwner: userToCancel.isGroupOwner
    })),
    chain((processedDetails) => userRepo.delete(processedDetails))
);
© www.soinside.com 2019 - 2024. All rights reserved.