Skip to content

Instantly share code, notes, and snippets.

@wkronemeijer
Last active June 18, 2016 17:53
Show Gist options
  • Save wkronemeijer/ca9d0f660c44624364ad4b690a01db17 to your computer and use it in GitHub Desktop.
Save wkronemeijer/ca9d0f660c44624364ad4b690a01db17 to your computer and use it in GitHub Desktop.
ES6 Module for creating what can be considered **almost** ADTs.
export interface InstanceConstructor<
/**Enum */ E,
/**Shared properties */ S,
/**Unique properties */ T
> {
/**Create new instance */
(diffs?: S & T): S & T;
/**Type guard for destructuring */
typecheck(object: {}): object is S & T;
/**For introspection, and to make IntelliSense work */
Kind: E;
}
export interface CaseConstructor<E, S> {
/**Use `Instance` to create a type alias for the enum */
Instance: S;
/**Create a new case for the `Enum` */
Case<T>(member: E, template: T): InstanceConstructor<E, S, T>;
}
const _EnumSymbol = Symbol('enum');
const _CaseSymbol = Symbol('case');
export function Enum<E, S>(
/**Host `enum` for names and IDs */ enum_: {},
/**`enum` member to help IntelliSense */ any_member: E,
/**Properties common to all `Case`s */ common_properties: S
): CaseConstructor<E, S> {
return {
Instance: common_properties,
Case<T>(member: E, template: T): InstanceConstructor<E, S, T> {
template[_EnumSymbol] = enum_;
template[_CaseSymbol] = +member;
template[Symbol.toStringTag] = enum_[+member] as string;
const create = (diffs?: S & T) => Object.assign({}, common_properties, template, diffs);
const helper = {
Kind: member,
typecheck(object: {}): object is S & T {
return (
template[_EnumSymbol] === object[_EnumSymbol] &&
template[_CaseSymbol] === object[_CaseSymbol]
);
},
};
return Object.assign(create, helper);
},
};
}
@wkronemeijer
Copy link
Author

Why use this: your ADTs typecheck and you can use IntelliSense on instance members

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment