Last active
February 5, 2021 18:52
-
-
Save HallexCosta/7a79b3800b646b80d46959e4959ba200 to your computer and use it in GitHub Desktop.
Error Pattern with Either
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
}) | |
} | |
})() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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({ | |
}) | |
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 } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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