Skip to content

Instantly share code, notes, and snippets.

@piotrgrundas
Forked from thiagoh/History|-1063032c|entries.json
Created July 20, 2019 16:30
Show Gist options
  • Save piotrgrundas/8f7f2a38e9721353d1c06fc3a2ccdac4 to your computer and use it in GitHub Desktop.
Save piotrgrundas/8f7f2a38e9721353d1c06fc3a2ccdac4 to your computer and use it in GitHub Desktop.
typescript / javascript version of Optional
type Function<T, R> = (value: T) => R;
type Supplier<T> = () => T;
type Consumer<T> = (value: T) => void;
export interface OptionalMonad<T> {
filter: (predicate: (value?: T) => boolean) => OptionalMonad<T>;
ifPresent: (consumer: (value?: T) => void) => void;
isPresent: () => boolean;
map: <R>(mapper: (value?: T) => R) => OptionalMonad<R>;
flatMap: <R>(mapper: (value?: T) => OptionalMonad<R>) => OptionalMonad<R>;
orElse: (value: T) => T;
orElseGet: (supplier: () => T) => T;
get: () => T;
}
interface Optional {
<T>(value?: T): OptionalMonad<T>;
of<T>(value: T): OptionalMonad<T>;
ofNullable<T>(value?: T): OptionalMonad<T>;
empty(): OptionalMonad<any>;
}
const OptionalCreator = <T>(value?: T): OptionalMonad<T> => {
const isPresent = typeof value !== 'undefined' && value !== null;
return {
filter: (predicate: (value?: T) => boolean): OptionalMonad<T> => {
return predicate(value) ? OptionalCreator(value) : OptionalCreator();
},
ifPresent: (consumer: Consumer<T>): void => {
consumer(value);
},
isPresent: (): boolean => isPresent,
map: <R>(mapper: Function<T, R>): OptionalMonad<R> => {
if (isPresent) {
return OptionalCreator(mapper(value));
}
return OptionalCreator();
},
flatMap: <R>(mapper: Function<T, OptionalMonad<R>>): OptionalMonad<R> => {
if (isPresent) {
return mapper(value);
}
return OptionalCreator();
},
orElse: (elseValue: T) => (isPresent ? value : elseValue),
orElseGet: (supplier: Supplier<T>) => (isPresent ? value : supplier()),
get: () => value,
};
};
const Optional = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.ofNullable = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.of = (<T>(value: T) => {
if (typeof value === 'undefined' || value === null) {
throw new Error('Optional value cannot be null/undefined');
}
return OptionalCreator(value);
}) as Optional;
Optional.empty = () => OptionalCreator();
export { Optional };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment