Skip to content

Instantly share code, notes, and snippets.

@mpkocher
Last active January 21, 2017 17:55
Show Gist options
  • Save mpkocher/d0d462ffdfd331b5a14734d33d29d08e to your computer and use it in GitHub Desktop.
Save mpkocher/d0d462ffdfd331b5a14734d33d29d08e to your computer and use it in GitHub Desktop.
Typescript PacBioOptions
/**
* Created by mkocher on 1/21/17.
*/
interface IdAble {
ix: string;
}
interface Primitive<T> {
value: T;
optionTypeId: string;
}
interface BaseOptionType<T> extends Primitive<T>, IdAble{
name: string;
description: string
}
abstract class BaseOption<T> implements BaseOptionType<T> {
readonly ix: string;
readonly name: string;
readonly description: string;
readonly value: T;
readonly optionTypeId: string;
constructor(ix: string, name: string, description: string, value: T) {
this.ix = ix;
this.name = name;
this.description = description;
this.value = value;
}
summary(): string {
return `PacBioOption id:${this.ix} type:${this.optionTypeId} value:${this.value} name:${this.name} desc:${this.description}`
}
}
class IntOption extends BaseOption<number> { readonly optionTypeId = "integer" }
class StringOption extends BaseOption<string> {readonly optionTypeId = "string"}
class FloatOption extends BaseOption<number> { readonly optionTypeId = "float"}
interface ChoiceAble<T> {
choices: T[];
}
abstract class BaseChoiceOption<T> implements BaseOptionType<T>, ChoiceAble<T> {
// This has to be duplicated because it's abstract?
readonly ix: string;
readonly name: string;
readonly description: string;
readonly optionTypeId: string;
readonly value: T;
public choices: T[];
constructor(ix: string, name: string, description: string, value: T, choices: T[]) {
this.ix = ix;
this.name = name;
this.description = description;
this.value = value;
this.choices = choices;
}
summary(): string {
return `PacBioOption id:${this.ix} type:${this.optionTypeId} value:${this.value} choices:${this.choices} name:${this.name} desc:${this.description}`
}
}
class IntChoiceOption extends BaseChoiceOption<number> { readonly optionTypeId = "choice_integer"}
class StringChoiceOption extends BaseChoiceOption<string> {readonly optionTypeId = "choice_string"}
// This is a bit wrong. This needs to deal with the JsNumber -> Float casting
class FloatChoiceOption extends BaseChoiceOption<string> {readonly optionTypeId = "float_string"}
// This should probably be done via type bounds, but TS doesn't seem to
// have it. This is a workaround
type OptionType = IntOption | StringOption | FloatOption | IntChoiceOption | StringChoiceOption | FloatChoiceOption
/**
* Example of Iterating over a list of polymorphic option types
*
* @param opt
* @returns {string}
*/
function toCustomSummary(opt: OptionType): string {
let sx = `Option Summary id:${opt.ix} value:${opt.value} type:${opt.optionTypeId}`;
// Running into problems here, because there's not a concrete choice type
// use "Type Guards?"
if (opt instanceof IntChoiceOption) {
return `${sx} choices:${opt.choices}`
} else {
return sx;
}
}
/**
* Return a Summary of the Task Options
* @param opts
* @returns {string}
*/
function optionsSummary(opts: OptionType[]): string {
return opts.map(toCustomSummary).join("\n");
}
/**
* Load From raw JSON from the services. This essentially
* a factory-ish pattern
* @param o
*/
function loadFrom(o: Object): OptionType {
let optionTypeId = o['optionTypeId'];
switch(optionTypeId) {
// Add more types here. Each Option constructor might need an explicit validation of
// of type
case "integer": return new IntOption(o['id'], o['name'], o['description'], o['value']);
case "string": return new StringOption(o['id'], o['name'], o['description'], o['value']);
case "choice_string": return new StringChoiceOption(o['id'], o['name'], o['description'], o['value'], o['choices'])
}
}
function sanity(): boolean {
// Example of Raw json from the services for a PacBioOption
let o = {
id: "x",
optionTypeId: "integer",
name: "My Name",
description: "Description",
value: 1298
};
let o2 = {
id: "y",
optionTypeId: "choice_string",
name: "My Name",
description: "Description",
value: "alpha",
choices: ["alpha", "beta", "gamma"]
};
let x = "description";
let intOpt = new IntOption("a", "Alpha", x, 1234);
let strOpt = new StringOption("b", "Beta", x, "beta-value");
let floatOpt = new FloatOption("g", "Gamma", x, 12345.0);
// choice examples
let intChoiceOpt = new IntChoiceOption("d", "delta", x, 1, [1,2,3]);
let strChoiceOpt = new StringChoiceOption("e", "epsilon", x, "a", ["a", "b", "c"]);
// Load and Convert Example from json
let myOption = loadFrom(o);
let myChoiceOpt = loadFrom(o2);
let opts: OptionType[] = [intOpt, strOpt, floatOpt, intChoiceOpt, strChoiceOpt, myOption, myChoiceOpt];
console.log("Default Task Option Summary");
console.log(opts.map(opt => opt.summary()).join("\n"));
let customSummary = optionsSummary(opts);
console.log("Custom Task Option Summary");
console.log(customSummary);
return true;
}
sanity();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment