Skip to content

Instantly share code, notes, and snippets.

@danthedaniel
Created March 20, 2018 18:23
Show Gist options
  • Save danthedaniel/5e70157152bb7c8a557360ce2c7b5cf5 to your computer and use it in GitHub Desktop.
Save danthedaniel/5e70157152bb7c8a557360ce2c7b5cf5 to your computer and use it in GitHub Desktop.
Rust's Option type in TypeScript.
/**
* An optional value. Can be null or a T.
*/
class Optional<T> {
private _val: T;
constructor(val: T) {
this._val = val;
}
/**
* Return the contained value.
*/
unwrap() {
return this._val;
}
/**
* Return the contained value or a default.
*
* @param def The default value.
*/
unwrap_or(def: T) {
return this.is_some() ? this._val : def;
}
/**
* Returns the contained value or computes it from a function.
*/
unwrap_or_else(func: () => T) {
return this.is_some() ? this._val : func();
}
/**
* Returns true if the option is not null.
*/
is_some() {
return this._val !== null;
}
/**
* Returns true if the option is null.
*/
is_none() {
return this._val === null;
}
/**
* Return the contained value.
*
* Throws msg if the value is null.
*
* @param msg Error message.
*/
expect(msg: string) {
if (this.is_some())
return this._val;
throw msg;
}
/**
* Maps an Optional<T> to Optional<U> by applying a function to the contained value.
*
* @param func The mapping function.
*/
map<U>(func: (val: T) => U) {
return this.is_some() ? new Optional<U>(func(this._val)) : new Optional<U>(null);
}
/**
* Maps an Optional<T> to Optional<U> by applying a function to the contained value.
*
* Uses the default value of the contained value is null.
*
* @param default The default value if null
* @param func The mapping function.
*/
map_or<U>(def: U, func: (val: T) => U) {
return this.is_some() ? new Optional<U>(func(this._val)) : new Optional<U>(def);
}
/**
* Maps an Optional<T> to Optional<U> by applying a function to the contained value.
*
* Uses a function to compute a default value if null.
*
* @param default Computes the default value if null
* @param func The mapping function.
*/
map_or_else<U>(def: () => U, func: (val: T) => U) {
return this.is_some() ? new Optional<U>(func(this._val)) : new Optional<U>(def());
}
/**
* Returns null if this contains null, otherwise returns optb.
*/
and<U>(optb: Optional<U>) {
return this.is_some() ? optb : new Optional<U>(null);
}
/**
* Returns nul if the contained value is null, otherwise returns the value of the func.
*/
and_then<U>(func: (val: T) => Optional<U>) {
return this.is_some() ? func(this._val) : new Optional<U>(null);
}
/**
* Returns this if the contained value is null, otherwise returns optb.
*/
or(optb: Optional<T>) {
return this.is_some() ? this : optb;
}
/**
* Returns this if the contained value is null, otherwise returns optb.
*/
or_else(func: () => Optional<T>) {
return this.is_some() ? this : func();
}
/**
* Takes the value out of the option, leaving null in its place.
*/
take() {
const ret = this._val;
this._val = null;
return new Optional<T>(ret);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment