Skip to content

Instantly share code, notes, and snippets.

@lolgesten
Forked from staltz/readme.ts
Last active May 5, 2018 14:52
Show Gist options
  • Save lolgesten/539fa110c3ba77beb23b2391b62e3bfc to your computer and use it in GitHub Desktop.
Save lolgesten/539fa110c3ba77beb23b2391b62e3bfc to your computer and use it in GitHub Desktop.
callbag-typescript-proof-of-concept
// tslint:disable no-expression-statement no-let
/**
* Callbag loves TypeScript
*
* Copy-paste this into http://www.typescriptlang.org/play/index.html
*/
enum CallbagOper {
Greet,
Deliver,
Terminate,
}
// A Callbag dynamically receives input of type I
// and dynamically delivers output of type O
type Callbag<I, O> = {
(t: CallbagOper.Greet, d: Callbag<O, I>): void;
(t: CallbagOper.Deliver, d: I): void;
(t: CallbagOper.Terminate, 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: CallbagOper, sink: any) => {
if (start !== CallbagOper.Greet) return;
inputSource(<any>CallbagOper.Greet, (t: CallbagOper, d?: A) => {
sink(t, t === CallbagOper.Deliver ? f(d!) : d);
});
};
return outputSource;
};
// Here is an example source
const numberListenable: Source<number> = (t: CallbagOper, d: any) => {
if (t !== CallbagOper.Greet) return;
const sink: Callbag<number, void> = d;
let i = 0;
setInterval(() => {
sink(CallbagOper.Deliver, i++);
}, 1000);
};
const stringListenable = map((x: number) => `${x}`)(numberListenable);
const sink = <T>(fn: (t: T) => void): Sink<T> => {
return (t: CallbagOper, d?: any) => {
if (t === CallbagOper.Deliver) {
fn(d);
}
};
};
// Example sink
const numberSink: Sink<number> = sink((d: number) => {
console.log(d);
});
const stringSink: Sink<string> = sink((d: string) => {
console.log(d.toUpperCase());
});
// This works:
numberListenable(CallbagOper.Greet, numberSink);
// This doesn't:
//numberListenable(CallbagOper.Greet, stringSink);
// This works:
stringListenable(CallbagOper.Greet, stringSink);
@lolgesten
Copy link
Author

  • Can typing be stronger? All those any and ?, shudder.
  • Isn't this just replacing the structural clarity of an observable with implicit magical overloaded void-functions?

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