javascript - fp-ts TaskEither'ı sağdaki Either ile zincirleme


İç içe geçmiş 2 isteğimden oluşan bir akışım var, burada 3 farklı sonuç olabilir:

  1. İsteklerden biri Hata döndürüyor
  2. Kullanıcı Anonim değil, Profili döndür
  3. Kullanıcı Anonim, false döndür

Her iki istek de bir hata fırlatabilir ve bu yüzden TaskEither uygular.

const isAuth = ():TE.TaskEither<Error, E.Either<true, false>>  
   => TE.tryCatch(() => Promise(...), E.toError)
const getProfile = ():TE.TaskEither<Error, Profile>  
   => TE.tryCatch(() => Promise(...), E.toError)

İlk istek, kullanıcı yetkilendirmesinin boolean durumunu döndürür. İkinci istek, kullanıcı yetkilendirilmişse profilini yükler.

Buna karşılık, bir sonraki imzayı, Hata veya Anonim/Profil ile Alma'yı istiyorum:

E.Either<Error, E.Either<false, Profile>>

Bunu şöyle yapmaya çalıştım:

pipe(
    isAuth()
    TE.chain(item => pipe(
      TE.fromEither(item),
      TE.mapLeft(() => Error('Anonimous')),
      TE.chain(getProfile)
    ))
  )

Ama karşılığında, E.Either<Error, Profile> alıyorum, bu uygun değil çünkü Error'dan Anonymous durumunu elle çıkarmam gerekiyor.

O soruyu nasıl çözebilirim?

Cevap #1

Gerçek kodu fazla basitleştirip basitleştirmediğini bilmiyorum, ama E.Either<true, false> sadece boolean ile izomorfik, o yüzden daha basit olanla devam edelim.

declare const isAuth: () => TE.TaskEither<Error, boolean>;
declare const getProfile: () => TE.TaskEither<Error, Profile>;

Sonra, onun yetkili olup olmadığına bağlı olarak bir koşul dalı ekleyip getProfile sonucunu sararsınız:

pipe(
  isAuth(),
  TE.chain(authed => authed 
    ? pipe(getProfile(), TE.map(E.right)) // wrap the returned value of `getProfile` in `Either` inside the `TaskEither`
    : TE.right(E.left(false))
  )
)

Bu ifade TaskEither<Error, Either<false, Profile>> türündedir. Muhtemelen doğru şekilde tip denetimi yapılabilmesi için bazı tip açıklamaları eklemeniz gerekiyor, ben kodu kendim çalıştırmadım.

DÜZENLEME:

Muhtemelen doğru tiplemeleri almak için lambdayı isimlendirilmiş bir fonksiyon olarak çıkarmanız gerekiyor, şöyle bir şey:

const tryGetProfile: (authed: boolean) => TE.TaskEither<Error, E.Either<false, Profile>> = authed
  ? pipe(getProfile(), TE.map(E.right))
  : TE.right(E.left(false));

const result: TE.TaskEither<Error, E.Either<false, Profile>> = pipe(
  isAuth(),
  TE.chain(tryGetProfile)
);

İlgili makaleler