Skip to content

Instantly share code, notes, and snippets.

@gregtatum
Created January 11, 2018 22:03
Show Gist options
  • Select an option

  • Save gregtatum/b8eeb86f3d54e5494418f2c138bd955d to your computer and use it in GitHub Desktop.

Select an option

Save gregtatum/b8eeb86f3d54e5494418f2c138bd955d to your computer and use it in GitHub Desktop.
Tag side effects with opaque types
/* @flow */
import type { Wrapped } from './wrap';
import { wrapWithSideEffect } from './wrap';
function addOne(a) {
return a + 1;
}
type AddOne = typeof addOne;
function withAddOne (fn: AddOne) {}
function withWrappedAddOne (fn: Wrapped<AddOne>) {}
withAddOne(addOne)
withWrappedAddOne(addOne) // Error
withAddOne(wrapWithSideEffect(addOne)) // Error
withWrappedAddOne(wrapWithSideEffect(addOne))
// This can be made generic too:
function onlyBareFns(fn: Function) {}
function onlyWrappedFns(wrappedFn: Wrapped<Function>) {}
onlyBareFns(addOne)
onlyWrappedFns(addOne) // Error
onlyBareFns(wrapWithSideEffect(addOne)) // Error
onlyWrappedFns(wrapWithSideEffect(addOne))
/* @flow */
export opaque type Wrapped<T> = T;
export function wrapWithSideEffect<T: Function>(fn: T): Wrapped<T> {
const wrapped: Wrapped<*> = (...args) => {
const result = fn(...args);
// Now do a side effect:
console.log("Dispatch side effect!", result)
return result
}
return (wrapped: Wrapped<*>)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment