Skip to content

Instantly share code, notes, and snippets.

@webstrand
Created March 21, 2019 17:11
Show Gist options
  • Select an option

  • Save webstrand/7ed8243adeefea26a176fa56b81c4c42 to your computer and use it in GitHub Desktop.

Select an option

Save webstrand/7ed8243adeefea26a176fa56b81c4c42 to your computer and use it in GitHub Desktop.
Derive a concrete type from a schematic type
type Spec = Atom | Dict | List;
type Atom = "bool" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "float32" | "float64" | "string" | "varuint" | "varint" | "buffer"
interface Dict { [key: string]: Spec }
interface List extends Array<Spec> { }
type TypeFromSpec<S extends Spec> = CondTypeFromAtom<S> | CondTypeFromDict<S> | CondTypeFromList<S>;
type TypeFromAtom<S extends Atom> = string;
type TypeFromDict<S extends Dict> = { [P in keyof S]: TypeFromSpec<S[P]> }
type TypeFromList<S extends List> = { [P in keyof S]: TypeFromSpec<S[P] extends Spec ? S[P] : never> }
type CondTypeFromAtom<S> = S extends Atom ? TypeFromAtom<S> : never;
type CondTypeFromDict<S> = S extends Dict ? TypeFromDict<S> : never;
type CondTypeFromList<S> = S extends List ? TypeFromList<S> : never;
const enum Buffer { }
interface Schema<S extends Dict> {
encode(data: TypeFromDict<S>): Buffer;
decode(data: Buffer): TypeFromDict<S>;
}
function build<S extends Dict>(schema: S): Schema<S>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment