Skip to content

Instantly share code, notes, and snippets.

@staltz
Created April 25, 2018 17:31
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save staltz/65454821a68d60a83c86e13052c4d17e to your computer and use it in GitHub Desktop.
Save staltz/65454821a68d60a83c86e13052c4d17e to your computer and use it in GitHub Desktop.
callbag-typescript-proof-of-concept
/**
* Callbag loves TypeScript
*
* Copy-paste this into http://www.typescriptlang.org/play/index.html
*/
// A Callbag dynamically receives input of type I
// and dynamically delivers output of type O
type Callbag<I, O> = {
(t: 0, d: Callbag<O, I>): void;
(t: 1, d: I): void;
(t: 2, d?: any): void;
};
// A source only delivers data
type Source<T> = Callbag<void, T>;
// A sink only receives data
type Sink<T> = Callbag<T, void>;
// An operator is a function Source<A> => Source<B>
const map = <A, B>(f: (x: A) => B) => (inputSource: Source<A>) => {
const outputSource: Source<B> = (start, sink) => {
if (start !== 0) return;
inputSource(0, (t, d) => {
sink(t, t === 1 ? f(d) : d);
});
};
return outputSource;
};
// Here is an example source
const numberListenable: Source<number> = (t: 0 | 1 | 2, d) => {
if (t !== 0) return;
const sink: Callbag<number, void> = d;
let i = 0;
setInterval(() => {
sink(1, i++);
}, 1000);
};
const stringListenable = map((x: number) => `${x}`)(numberListenable);
// Example sink
const numberSink: Sink<number> = (t: 0 | 1 | 2, d) => {
if (t === 1) {
console.log(d);
}
};
const stringSink: Sink<string> = (t: 0 | 1 | 2, d) => {
if (t === 1) {
console.log(d.toUpperCase());
}
};
// This works:
numberListenable(0, numberSink);
// This doesn't:
numberListenable(0, stringSink);
// This works:
stringListenable(0, stringSink);
@StreetStrider
Copy link

Awesome typings, especially in Source & Sink part. I like the simplicity.

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