Created
May 3, 2019 22:19
-
-
Save reverofevil/c3c1c05e508194a46b5761a8b87088bb to your computer and use it in GitHub Desktop.
Isomorphic API typing
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
import { Type, URIS as Uris } from 'fp-ts/lib/HKT'; | |
type JsonMap = { [K: string]: Json } | |
interface JsonArray extends Array<Json> {} | |
type Json = JsonMap | JsonArray | number | string | boolean | null | |
interface Prim<Uri extends Uris> { | |
num: Type<Uri, number>; | |
obj: <O>(ss: { [K in keyof O]: Type<Uri, O[K]> }) => Type<Uri, O>; | |
} | |
type Serializer<T> = (t: T) => Json; | |
type SerializerUri = 'Serializer' | |
type Deserializer<T> = (j: Json) => T; | |
type DeserializerUri = 'Deserializer' | |
declare module 'fp-ts/lib/HKT' { | |
interface URI2HKT<A> { | |
Serializer: Serializer<A>; | |
Deserializer: Deserializer<A>; | |
} | |
} | |
const parser: Prim<DeserializerUri> = { | |
num(j: Json): number { | |
if (typeof j !== 'number') { | |
throw new Error('Number expected'); | |
} else { | |
return j; | |
} | |
}, | |
obj<O>(ss: { [K in keyof O]: Deserializer<O[K]> }) { | |
return (j: Json): O => { | |
if (typeof j !== 'object' || Array.isArray(j)) { | |
throw new Error('Object expected'); | |
} | |
return Object.keys(ss).reduce((result: O, key: string) => { | |
return {...result, [key]: (ss as any)[key]((j as any)[key])}; | |
}, {} as O); | |
}; | |
} | |
}; | |
const printer: Prim<SerializerUri> = { | |
num(n: number): Json { | |
return n; | |
}, | |
obj<O>(ss: { [K in keyof O]: Serializer<O[K]> }) { | |
return (o: O): Json => { | |
return Object.keys(ss).reduce((result: JsonMap, key: string) => { | |
return {...result, [key]: (ss as any)[key]((o as any)[key])}; | |
}, {} as JsonMap); | |
}; | |
} | |
}; | |
const schema = <Uri extends Uris>(p: Prim<Uri>) => p.obj({ | |
a: p.num, | |
b: p.obj({ | |
c: p.num, | |
}), | |
}); | |
const r = schema(parser)(schema(printer)({a: 1, b: {c: 2}})); | |
console.log(r.b.c); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment