Skip to content

Instantly share code, notes, and snippets.

@mvaldesdeleon
Last active August 12, 2018 01:12
Show Gist options
  • Save mvaldesdeleon/99ac9fb3da6bb5a0cd2b63ea8a0e039c to your computer and use it in GitHub Desktop.
Save mvaldesdeleon/99ac9fb3da6bb5a0cd2b63ea8a0e039c to your computer and use it in GitHub Desktop.
interface Boring {
bore: () => boolean
}
interface Fooable<A> {
foo: () => string,
unfoo: (s: string) => A
}
interface Barable<A> {
bar: (a: A) => A
rab: () => A
}
// class Qux implements Fooable<number>, Barable<number> {
// constructor (readonly value: number) {}
// foo() {
// return this.value.toString();
// }
// unfoo(s: string) {
// return parseInt(s, 10)
// }
// bar(a: number) {
// return this.value + a;
// }
// rab() {
// return 0;
// }
// }
class BetterQux implements Fooable<BetterQux>, Barable<BetterQux> {
constructor (readonly value: number) {}
foo() {
return this.value.toString();
}
unfoo(s: string) {
return new BetterQux(parseInt(s, 10));
}
bar(a: BetterQux) {
return new BetterQux(this.value + a.value);
}
rab() {
return new BetterQux(0);
}
}
let a = new BetterQux(1);
let b = new BetterQux(2);
console.log(a.bar(b));
console.log(a.foo());
class BarableThing<A extends Barable<A>> implements Barable<BarableThing<A>> {
constructor(readonly value: A[]) {}
bar(a: BarableThing<A>) {
if (this.value.length > a.value.length) {
return new BarableThing(a.value.map((a, i) => a.bar(this.value[i])));
} else {
return new BarableThing(this.value.map((x, i) => x.bar(a.value[i])));
}
}
rab() {
return new BarableThing(this.value.map(a => a.rab()));
}
}
class FooableThing<A extends Fooable<A>> implements Fooable<FooableThing<A>> {
constructor(readonly value: A[]) {}
foo() {
return '';
}
unfoo(s: string) {
return new FooableThing([]);
}
}
class FooBarableThing<A extends Fooable<A> & Barable<A>> implements Fooable<FooBarableThing<A>> {
constructor(readonly value: A[]) {}
bar(a: FooBarableThing<A>) {
if (this.value.length > a.value.length) {
return new FooBarableThing(a.value.map((a, i) => a.bar(this.value[i])));
} else {
return new FooBarableThing(this.value.map((x, i) => x.bar(a.value[i])));
}
}
rab() {
return new FooBarableThing(this.value.map(a => a.rab()));
}
foo() {
return '';
}
unfoo(s: string) {
return new FooBarableThing([]);
}
}
type Woop<A> = Fooable<A> | Barable<A> | Fooable<A> & Barable<A> | any
type Thing<A> = A extends Fooable<A> ? (A extends Barable<A> ? FooBarableThing<A> : FooableThing<A>) :
A extends Barable<A> ? BarableThing<A> :
never;
function isFoo<A>(a: Woop<A>): a is Fooable<A> {
return 'foo' in a;
}
function isBar<A>(a: Woop<A>): a is Barable<A> {
return 'bar' in a;
}
function thing<A>(a: Woop<A>[]): Thing<A> {
if (isFoo(a[0]) && isBar(a[0])) {
return new FooBarableThing(a) as Thing<A>;
} else if (isFoo(a[0])) {
return new FooableThing(a) as Thing<A>;
} else if (isBar(a[0])) {
return new BarableThing(a) as Thing<A>;
}
}
let x = thing([a, b]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment