Miłosz Piechocki
interface Employee {
id: number;
name: string;
supervisorId?: number;
}
class EmployeeRepository {
private employees: Employee[] = [ /* ... */ ];
get(id: number): Employee {
return this.employees.find(e => e.id === id);
}
}
function getEmployeeName(id: number) {
const employee = repository.get(id);
if (employee !== undefined) {
return employee.name;
}
return undefined;
}
function getEmployeeSupervisor(id: number) {
const employee = repository.get(id);
if (employee !== undefined &&
employee.supervisorId !== undefined) {
return repository.get(employee.supervisorId);
}
return undefined;
}
function getEmployeeSupervisorName(id: number) {
const employee = repository.get(id);
if (employee !== undefined &&
employee.supervisorId !== undefined) {
const supervisor = repository.get(employee.supervisorId);
if (supervisor !== undefined)
return supervisor.name;
}
return undefined;
}
function getEmployeeSupervisorNameSafe(id: number) {
if (id !== undefined) {
const employee = repository.get(id);
if (employee !== undefined &&
employee.supervisorId !== undefined) {
const supervisor = repository.get(employee.supervisorId);
if (supervisor !== undefined)
return supervisor.name;
}
}
return undefined;
}
interface Option<T> {
getOrElse(defaultValue: T): T;
}
class Some<T> implements Option<T> {
constructor(private value: T) {}
getOrElse(defaultValue: T): T {
return this.value;
}
}
class None<T> implements Option<T> {
getOrElse(defaultValue: T): T {
return defaultValue;
}
}
interface Employee {
id: number;
name: string;
supervisorId: Option<number>;
}
class EmployeeRepository {
private employees: Employee[] = [ /* ... */ ];
get(id: number): Option<Employee> {
const result = this.employees.find(e => e.id === id);
return result ? new Some(result) : new None();
}
}
interface Option<T> {
getOrElse(defaultValue: T): T;
map<R>(project: (inner: T) => R)
: Option<R>;
}
class Some<T> implements Option<T> {
map<R>(project: (inner: T) => R)
: Option<R> {
return new Some(project(this.value));
}
// ...
}
class None<T> implements Option<T> {
map<R>(project: (inner: T) => R)
: Option<R> {
return new None<R>();
}
// ...
}
function getEmployeeName(id: number) {
const employee = repository.get(id);
if (employee !== undefined) {
return employee.name;
}
return undefined;
}
function getEmployeeName(id: number): Option<string> {
return repository.get(id).map(e => e.name);
}
function getEmployeeSupervisor(id: number)
: Option<Option<number>> {
return repository.get(id)
.map(e => e.supervisorId);
}
export interface Option<T> {
getOrElse(defaultValue: T): T;
map<R>(project: (inner: T) => R): Option<R>;
flatMap<R>(project: (inner: T) => Option<R>)
: Option<R>;
}
function getEmployeeSupervisorNameSafe(id: number) {
if (id !== undefined) {
const employee = repository.get(id);
if (employee !== undefined &&
employee.supervisorId !== undefined) {
const supervisor = repository.get(employee.supervisorId);
if (supervisor !== undefined)
return supervisor.name;
}
}
return undefined;
}
function getEmployeeSupervisorNameSafe(idOption: Option<number>) {
return idOption
.flatMap(id => repository.get(id))
.flatMap(employee => employee.supervisorId)
.flatMap(supervisorId => repository.get(supervisorId))
.map(supervisor => supervisor.name);
}
interface Employee {
id: number;
name: string;
supervisorId: Result<number, string>;
}
get(id: number): Result<Employee, string> {
const result = this.employees.find(e => e.id === id);
return result
? new Success(result)
: new Failure("No employee found");
}
function getEmployeeSupervisorNameSafe(idResult)
: Result<string, string> {
return idResult
.flatMap(id => repository.get(id))
.flatMap(employee => employee.supervisorId)
.flatMap(supervisorId => repository.get(supervisorId))
.map(supervisor => supervisor.name);
}
private employees: Employee[] = [
{ id: 1, name: "Piotr Kowalski",
supervisorId: new Success(2) },
{ id: 2, name: "Katarzyna Grabowska",
supervisorId: new Failure("No supervisor") },
{ id: 3, name: "Piotr Zientara",
supervisorId: new Success(2) },
];
getEmployeeSupervisorNameSafe(new Success(1));
// Success {value: "Katarzyna Grabowska"}
getEmployeeSupervisorNameSafe(new Success(2));
// Failure {failure: "No supervisor"}
getEmployeeSupervisorNameSafe(new Success(5));
// Failure {failure: "No employee found"}
interface Employee {
id: number;
name: string;
supervisorId: Promise<number>;
}
get(id: number): Promise<Employee> {
const result = this.employees.find(e => e.id === id);
return result
? Promise.resolve(result)
: Promise.reject("No employee found");
}
function getEmployeeSupervisorNameSafe(idPromise)
: Promise<number>{
return idPromise
.then(id => repository.get(id))
.then(employee => employee.supervisorId)
.then(supervisorId => repository.get(supervisorId))
.then(supervisor => supervisor.name);
}
interface Employee {
id: number;
name: string;
supervisorId: Observable<number>;
}
get(id: number): Observable<Employee> {
const result = this.employees.find(e => e.id === id);
return result
? Observable.of(result)
: Observable.throw("No employee found");
}
function getEmployeeSupervisorNameSafe(id$): Observable<number> {
return id$
.flatMap(id => repository.get(id))
.flatMap(employee => employee.supervisorId)
.flatMap(supervisorId => repository.get(supervisorId))
.map(supervisor => supervisor.name);
}
flatMap
(a.k.a. bind
)return