簡體   English   中英

如何 pipe 並鏈接一個使用來自 `fp-ts` 的多個 `Eithers` 和 `Promises` 的操作

[英]How to pipe and chain an operation that uses multiple `Eithers` and `Promises` from `fp-ts`

我是fp-ts新手,我正在嘗試創建一個類似函數的方法:

  1. 解析不記名令牌
  2. 使用解析的令牌檢查用戶是否有效
import { Request } from 'express';
import { either } from 'fp-ts';
import { pipe } from 'fp-ts/lib/function';

// * Parse the token
declare const parseRawToken: (rawToken: string | undefined) => either.Either<Error, string>;

// * Interface of the validate method
type MakeIsRequestAuthenticated = (
  validateUserWithToken: (data: string) => Promise<either.Either<Error, void>>,
) => (request: Request) => Promise<either.Either<Error, void>>;

我想將這些驗證鏈接到 pipe 中,所以我嘗試通過以下方式實現驗證:

export const makeIsRequestAuthenticated: MakeIsRequestAuthenticated = validateUserWithToken => {
  // * Validate the request
  return async request => {
    return pipe(
      parseRawToken(request.header('Authorization')),
      either.chain(validateUserWithToken)
      );
  };
};

但它給了我以下錯誤:

Argument of type '(data: string) => Promise<Either<Error, void>>' is not assignable to parameter of type '(a: string) => Either<Error, void>'.
  Type 'Promise<Either<Error, void>>' is not assignable to type 'Either<Error, void>'.ts(2345)

我曾嘗試用TaskEither和其他一些解決方案替換Promise ,但都沒有用

我想使用chain或其他一些方法能夠在pipe中執行所有這些操作

希望這能有所幫助。

  • 我稍微修改了 validate 方法的接口以返回請求,允許另一個處理程序接受它並在驗證后執行任何操作
  • 我修改了 validateUserWithToken 的接口以返回 TaskEither<Error, void> 而不是 promise。
import { Request } from 'express';
import { pipe } from 'fp-ts/lib/function';
import * as TE from "fp-ts/TaskEither";
import * as E from "fp-ts/Either";
import { assert } from 'console';

// * Parse the token (dummy implementation)
const parseRawToken = (rawToken: string | undefined) =>
    rawToken ? E.right(rawToken) : E.left(new Error("Invalid token"));

// * Interface of the validate method (changed return type to TastEither<Error, Request>)
type MakeIsRequestAuthenticated = (
    validateUserWithToken: (data: string) => TE.TaskEither<Error, void>,
) => (request: Request) => TE.TaskEither<Error, Request>;

//Actual implementation
export const makeIsRequestAuthenticated: MakeIsRequestAuthenticated =
    validateUser => (request: Request) =>
        pipe(
            request.header("Authorization"), //returns string | undefined
            parseRawToken, //returns  Either<Error, string>
            TE.fromEither, //To TaskEither
            TE.map(validateUser), //validate token, returns TE.TaskEither<Error, TE.TaskEither<Error, void>>
            TE.flatten, //To unwrap nested TaskEither<Error, void> 
            TE.map(() => request) //If no errors return request
        )

//Mock request
const mockRequest = {
    header: (name: string) => "fake token",
    body: {
        userName: "MsFake",
    }
} as Request;

//Dummy implementations for tokenValidators: sucess and fail
const mockValidToken: (token: string) => TE.TaskEither<Error, void> =
    (token: string) => TE.right(void 0);
const mockInValidToken: (token: string) => TE.TaskEither<Error, void> =
    (token: string) => TE.left(new Error("Token not valid"));

//Test
const fail = makeIsRequestAuthenticated(mockInValidToken)(mockRequest);
const sucess = makeIsRequestAuthenticated(mockValidToken)(mockRequest);

sucess().then(d => assert(d._tag === "Right"));
fail().then(d => assert(d._tag === "Left"));

現在MakeIsRequestAuthenticated方法返回一個TaskEither<Error, Request>並且您可以將它與任何將Request作為參數的方法鏈接起來。 從現在開始,您可以處理 taskEither 而不是 promises,但這應該不是問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM