Effect CommunityEC
Effect Community2mo ago
9 replies
janglad

Transforming Struct to Class with Error Handling in Effect Typescript

how do you best transform from a struct to a class if you want to transform based on the decoded struct (so we get branded types etc)? Basically it seems like what I'd want is the equivalent of SomeClass.make but where I get access to the possible
ParseError
and can properly handle it in my transformation. Would
transformOrFail
+ a try/catch wrap around make be the best option here?

import { Schema } from "effect"

const UserId = Schema.Number.pipe(Schema.brand("UserId"))
type UserId = typeof UserId.Type

const UserStruct = Schema.Struct({
  id: UserId,
  age: Schema.Number
})

class UserClass extends Schema.Class<UserClass>("UserClass")({
  id: UserId,
  age: Schema.Int
}) {}

const UserClassFromStruct = UserStruct.pipe(Schema.transform(Schema.typeSchema(UserClass), {
  encode: (decoded) => decoded,
  decode: (encoded) => {
    // I want to have branded types here
    encoded.id satisfies UserId
    return encoded
  },
  strict: true
}))

console.log(
  //       '   └─ Expected UserClass, actual {"id":1,"age":1}'
  Schema.decodeEither(UserClassFromStruct)({ id: 1, age: 1 })
)

const UserClassFromStruct2 = UserStruct.pipe(Schema.transform(Schema.typeSchema(UserClass), {
  encode: (decoded) => decoded,
  decode: (encoded) => {
    // I want to have branded types here
    encoded.id satisfies UserId
    return UserClass.make(encoded)
  },
  strict: true
}))

try {
  Schema.decodeEither(UserClassFromStruct2)({ id: 1, age: 1.5 })
} catch (e) {
  // This throws the ParseError from UserClass.make
  //     '         └─ Expected an integer, actual 1.5'
  console.log("Thrown", e)
}


https://effect.website/play/#24de8d9aa751
Was this page helpful?