Last active
August 12, 2018 01:12
-
-
Save mvaldesdeleon/99ac9fb3da6bb5a0cd2b63ea8a0e039c to your computer and use it in GitHub Desktop.
This file contains hidden or 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
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