Skip to content

Instantly share code, notes, and snippets.

@kana-sama
Created March 12, 2021 21:29
Show Gist options
  • Save kana-sama/9d347aebbdb2609f09fc6c91c0524f82 to your computer and use it in GitHub Desktop.
Save kana-sama/9d347aebbdb2609f09fc6c91c0524f82 to your computer and use it in GitHub Desktop.
declare type Space = " " | "\n" | "\t";
declare type LetterL = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
declare type Letter = LetterL | Uppercase<LetterL>;
declare type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
declare type Alphanumeric = Letter | Digit;
declare type Trim<S> = S extends `${Space}${infer S}` ? Trim<S> : S extends `${infer S}${Space}` ? Trim<S> : S;
declare type ParseIdent2<S, OS> = S extends `${Alphanumeric}${infer X}` ? ParseIdent2<X, OS> : S extends "" ? OS : never;
declare type ParseIdent<S> = S extends `${Letter}${infer X}` ? ParseIdent2<X, S> : never;
declare type ParseIfaceProperty<S> = S extends `${infer Name}: ${infer Type}` ? {
ok: true;
name: ParseIdent<Trim<Name>>;
type: Trim<Type>;
} : {
ok: false;
};
declare type ParseIfaceProperties<S> = S extends `${infer Head},${infer Tail}` ? Head extends "" ? ParseIfaceProperties<Tail> : [ParseIfaceProperty<Head>, ...ParseIfaceProperties<Tail>] : S extends "" ? [] : [ParseIfaceProperty<S>];
declare type ParseType<S> = {
ok: false;
};
declare type ParseInterface<S> = S extends `interface ${infer IfaceName}{${infer IfaceProperties}}` ? ParseIfaceProperties<IfaceProperties> extends (infer R & {
ok: true;
}[]) ? {
ok: true;
type: "iface";
name: ParseIdent<Trim<IfaceName>>;
properties: R;
} : {
ok: false;
i: ParseIfaceProperties<IfaceProperties>;
} : {
ok: false;
};
declare type Primitives = {
number: number;
string: string;
};
declare type MatchType<T> = T extends keyof Primitives ? Primitives[T] : never;
declare type AddProps<Ob, Props> = Props extends [infer A, ...infer Rest] ? A extends {
name: infer K;
type: infer T;
} ? AddProps<Ob & {
[k in K & string]: MatchType<T>;
}, Rest> : never : Props extends [infer A] ? A extends {
name: infer K;
type: infer T;
} ? Ob & {
[k in K & string]: MatchType<T>;
} : never : Ob;
declare type QuotedInterface<S> = ParseInterface<Trim<S>> extends {
ok: true;
properties: infer P;
} ? AddProps<{}, P> : never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment