UNPKG

iron-enum

Version:

Rust like enums for Typescript

105 lines (92 loc) 2.02 kB
import { IronEnum, EnumFactoryUnion } from "../mod"; // recursive Enum type definition type ColTypes = { Int: { default?: number }; Text: { default?: string }; List: { of: EnumFactoryUnion<ColTypes> // inner reference }; Object: { props: Record<string, EnumFactoryUnion<ColTypes>> // inner reference }; } // Map Enum variants to primitves type PrimitiveMap = { Int: number; Text: string; }; type ColumnToType<T> = /* List ----------------------------------------------------------- */ T extends { tag: "List"; payload: infer P } ? P extends { of: infer Inner } ? ColumnToType<Inner>[] : never /* Object --------------------------------------------------------- */ : T extends { tag: "Object"; payload: infer P } ? P extends { props: infer Props } ? { [K in keyof Props]: ColumnToType<Props[K]> } : never /* Leaves --------------------------------------------------------- */ : T extends { tag: infer Tag } ? Tag extends keyof PrimitiveMap ? PrimitiveMap[Tag] : never : never; type SchemaPrimitives<S> = S extends Record<string, EnumFactoryUnion<ColTypes>> ? { [K in keyof S]: ColumnToType<S[K]> } : never; // Initilize our fancy type const Col = IronEnum<ColTypes>(); // example usage const ProductTable = { id: Col.Int(), name: Col.Text(), tags: Col.List({ of: Col.Text() }), info: Col.Object({ props: { dimensions: Col.Object({ props: { width: Col.Int(), height: Col.Int(), depth: Col.Int() } }), gallery: Col.List({ of: Col.Text() }) } }) } type ProductRow = SchemaPrimitives<typeof ProductTable>; /* ^? ProductRow = { id: number; name: string; tags: string[]; info: { dimensions: { width: number; height: number; depth: number; }; gallery: string[]; }; } */ const demo: ProductRow = { id: 1, name: "Totoro Plush", tags: ["cute", "collectible"], info: { dimensions: { width: 10, height: 15, depth: 8 }, gallery: ["/img/01.jpg", "/img/02.jpg"] } }; console.log(demo);