Skip to content

Instantly share code, notes, and snippets.

@HallexCosta
Last active February 5, 2021 18:52
Show Gist options
  • Save HallexCosta/7a79b3800b646b80d46959e4959ba200 to your computer and use it in GitHub Desktop.
Save HallexCosta/7a79b3800b646b80d46959e4959ba200 to your computer and use it in GitHub Desktop.
Error Pattern with Either
export type Either<L, A> = Left<L, A> | Right<L, A>
export class Left<L, A> {
readonly value: L
constructor (value: L) {
this.value = value
}
isLeft (): this is Left<L, A> {
return true
}
isRight (): this is Right<L, A> {
return false
}
}
export class Right<L, A> {
readonly value: A
constructor (value: A) {
this.value = value
}
isLeft (): this is Left<L, A> {
return false
}
isRight (): this is Right<L, A> {
return true
}
}
export const left = <L, A>(l: L): Either<L, A> => {
return new Left<L, A>(l)
}
export const right = <L, A>(a: A): Either<L, A> => {
return new Right<L, A>(a)
}
import { UserValidator } from './UserValidator'
class Factory {
private static userValidator: UserValidator
private static userRepository: UserRepository
public static userValidatorInstance() {
if (Factory.userValidator instanceof UserValidator) {
return Factory.userValidator
}
Factory.userValidator = new UserValidator()
return Factory.userValidator
}
public static userRepositoryInstance(userValidator: UserValidator) {
if (Factory.userRepository instanceof UserRepository) {
return Factory.userRepository
}
Factory.userRepository = new UserRepository(userValidator)
return Factory.userRepository
}
}
import { user } from './User'
import { userRepository } from './UserRepository'
(async () => {
try {
const userAlreadyExists = await userRepository.findByEmail(user.email)
if (userAlreadyExists.isRight()) {
throw new Error('User already exists')
}
await userRepository.create(user)
// Simulate return response success
return response.send(201).json({
message: 'User created',
data: user
})
} catch (e) {
// Simulate return response bad
return response.send(400).json({
message: e.message
})
}
})()
export class User {
private readonly name: string
private readonly email: string
private readonly password: string
constructor(props: User) {
Object.assing(props, this)
Object.freeze(this)
}
}
export const user = new User({
name: 'Hállex da Silva Costa',
email: '[email protected]',
password: '123'
})
import { Factory } from './Factory'
import { userValidator } from './UserValidator'
import { Either, left, right } from './Either'
export class UserRepository {
constructor(private validator: UserValidator) {}
}
async function findByEmail(email: string): Promise<Either<Error, User>> {
if (!this.valdiator.isEmail(data.name)) {
return left(new Error('Email not valid'))
}
// Simulate connection with database
const db = this.database.connect()
const user = await db.collection('users').findOne({
email
})
if (!user) {
return left(new Error('User not found'))
}
return right(new User(user))
}
async function create(data: User): Promise<Either<Error, void>> {
if (this.findByEmail(data.email)) {
return left(new Error('User already exists'))
}
console.log('Saving...', data)
}
const userRepository = Fatory.userRepositoryInstance(userValidator)
create.apply(repository, [user])
findByEmail.apply(repository, [user.email])
export { userRepository }
import { Factory } from './Factory'
export class UserValidator {}
function validate(user: User): boolean {
return this.isEmail(user.email)
}
function isEmail(email: string): boolean {
const tester = /@/g
return tester.test(email)
}
const userValidator = Factory.userValidatorInstance()
isEmail.apply(userValidator, [user.name])
validate.apply(userValidator, [user])
export { userValidator }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment