Skip to content

Instantly share code, notes, and snippets.

@spocke
Created August 2, 2019 06:26
Show Gist options
  • Save spocke/543c45851c554d3dece5a6e7cb11182d to your computer and use it in GitHub Desktop.
Save spocke/543c45851c554d3dece5a6e7cb11182d to your computer and use it in GitHub Desktop.
adt.ts
// -------------------- Experiment A
// Adt module
interface Matcher<A> {
match<T>(a: { [P in keyof A]: (...x: any[]) => T }): T; // Can't put a constraint on arguments of x
fold<T>(...x: Array<(...x: any[]) => T>): T // Can't put a constraint on the arguments
}
const Adt: any = {
generate: () => {}
};
// Implementation
interface ResultType {
error: (message: string) => Result;
value: (value: number) => Result;
}
interface Result extends Matcher<ResultType> {};
const Result: ResultType = Adt.generate([
{ error: [ 'message' ] },
{ value: [ 'value' ] }
]);
// 1. Return type can be inferred
// 2. Has exhaustiveness checking
// 3. Doesn't have argument checking
// 4. Checks if all cases has the same return type
const resultToString = (result: Result) => result.match({
error: (message: string) => message.trim(),
value: (value: number) => value > 2 ? 'big' : 'small'
});
// 1. Return type can be inferred
// 2. Doesn't have exhaustiveness checking
// 3. Doesn't have argument checking
// 4. Checks if all cases has the same return type
const resultToStringFold = (result: Result) => result.fold(
(message: string) => message.trim(),
(value: number) => value > 2 ? 'big' : 'small'
);
const str1 = resultToString(Result.error('Some error')).trim();
const str2 = resultToString(Result.value(42)).trim();
export {
Result,
resultToString
};
// -------------------- Experiment B
// Adt module
interface Matcher<A> {
match<T>(m: A): T // Can't put a constraint on the return values in A
fold<T>(...x: Array<(...x: any[]) => T>): T // Can't put a constraint on the arguments
}
const Adt: any = {
generate: () => {}
};
// Implementation
interface ResultType<T=Result> {
error: (message: string) => T;
value: (value: number) => T;
}
interface Result extends Matcher<ResultType<any>> {};
const Result: ResultType = Adt.generate([
{ error: [ 'message' ] },
{ value: [ 'value' ] }
]);
// 1. Return type can't be inferred
// 2. Has exhaustiveness checking
// 3. Has argument checking
// 4. Doesn't check if all cases has the same return type
const resultToStringMatch = (result: Result): string => result.match({
error: (message) => message.trim(),
value: (value) => value > 2 ? 'big' : 'small'
});
// 1. Return type can be inferred
// 2. Doesn't have exhaustiveness checking
// 3. Doesn't have argument checking
// 4. Checks if all cases has the same return type
const resultToStringFold = (result: Result) => result.fold(
(message: string) => message.trim(),
(value: number) => value > 2 ? 'big' : 'small'
);
const str1 = resultToStringMatch(Result.error('Some error')).trim();
const str2 = resultToStringMatch(Result.value(42)).trim();
export {
Result,
resultToStringMatch
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment