Created
August 2, 2019 06:26
-
-
Save spocke/543c45851c554d3dece5a6e7cb11182d to your computer and use it in GitHub Desktop.
adt.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -------------------- 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