Skip to content

Instantly share code, notes, and snippets.

@kana-sama
Created March 13, 2021 13:50
Show Gist options
  • Save kana-sama/2308d78d98836f202a4b64f810ca40da to your computer and use it in GitHub Desktop.
Save kana-sama/2308d78d98836f202a4b64f810ca40da to your computer and use it in GitHub Desktop.
type ok<value, rest> = [value, rest];
type fail = [];
type fix_intersection<a> = { [key in keyof a]: a[key] }
type parse_substring<sub extends string, s1> =
s1 extends `${sub}${infer s2}` ?
ok<null, s2> : fail;
type space = " " | "\n";
type parse_space<s1> =
s1 extends `${space}${infer s2}` ? parse_space<s2> : ok<null, s1>;
type parse_name<s1> =
s1 extends `${infer name}:${infer s2}` ?
ok<name, `:${s2}`> : fail;
type prims = {
number: number,
string: string,
boolean: boolean,
};
type parse_type<s1> =
s1 extends `${keyof prims}${infer s2}` ?
s1 extends `${infer type_}${s2}` ? ok<prims[type_ & keyof prims], s2> : fail :
parse_record<s1>;
type parse_field<s1> =
parse_name<s1> extends ok<infer name, infer s2> ?
name extends string ?
parse_substring<": ", s2> extends ok<null, infer s3> ?
parse_type<s3> extends ok<infer type_, infer s4> ?
ok<{[k in name]: type_}, s4> : fail : fail : fail : fail;
type parse_fields<s1> =
parse_field<s1> extends ok<infer field, infer s2>
? parse_substring<",", s2> extends ok<null, infer s3> ?
parse_space<s3> extends ok<null, infer s4> ?
parse_fields<s4> extends ok<infer fields, infer s5> ?
ok<fix_intersection<field & fields>, s5> : fail : fail : ok<field, s2>
: ok<{}, s1>
type parse_record<s1> =
parse_substring<"{", s1> extends ok<null, infer s2> ?
parse_space<s2> extends ok<null, infer s3> ?
parse_fields<s3> extends ok<infer fields, infer s4> ?
parse_space<s4> extends ok<null, infer s5> ?
parse_substring<"}", s5> extends ok<null, infer s6> ?
ok<fields, s6> : fail : fail : fail : fail : fail;
type run<result> = result extends ok<infer value, ""> ? value : never;
const asrc = `{
a: number, e: boolean,
b: { c: string, d: string }
}`;
type a = run<parse_record<typeof asrc>>;
const a: a = { e: true, a: 1, b: { c: "hello", d: "world" } };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment