UNPKG

ts-variant-gen

Version:

Small utility to generate F#/Kotlin-style discriminated unions (variant types) for TypeScript projects

131 lines (130 loc) 4.76 kB
"use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateFile = exports.generateType = void 0; var fs = require("fs"); var path = require("path"); var VariantBuilder = /** @class */ (function () { function VariantBuilder() { this.fields = []; } VariantBuilder.prototype.withField = function (name, type) { this.fields.push({ name: name, type: type, }); }; return VariantBuilder; }()); var TypeBuilder = /** @class */ (function () { function TypeBuilder() { this.variants = []; } TypeBuilder.prototype.withVariant = function (name, variantConfig) { var fields = variantConfig ? (function () { var builder = new VariantBuilder(); variantConfig(builder); return builder.fields; })() : []; this.variants.push({ name: name, fields: fields, }); }; return TypeBuilder; }()); var FileBuilder = /** @class */ (function () { function FileBuilder() { this.types = []; } FileBuilder.prototype.withType = function (name, typeConfig) { this.types.push(exports.generateType(name, typeConfig)); }; return FileBuilder; }()); var generateDiscriminators = function (typeName, variants) { return __spreadArray(__spreadArray([], variants.map(function (v) { return "const " + typeName + "_" + v.name + "_Discriminator = Symbol(\"" + typeName + "_" + v.name + "_Discriminator\")"; })), [ "", ]).join("\n"); }; var generateVariantFields = function (variant, delimiter, prefix) { if (delimiter === void 0) { delimiter = ", "; } if (prefix === void 0) { prefix = ""; } return variant.fields.map(function (f) { return "" + prefix + f.name + ": " + f.type; }).join(delimiter); }; var generateVariantType = function (typeName, variant) { return [ "type " + typeName + "_" + variant.name + " = {", "\t_t: typeof " + typeName + "_" + variant.name + "_Discriminator", generateVariantFields(variant, "\n", "\t"), "}", "", ].join("\n"); }; var generateVariantTypes = function (typeName, variants) { return __spreadArray([], variants.map(function (v) { return generateVariantType(typeName, v); })).join("\n"); }; var generateMainType = function (typeName, variants) { return __spreadArray(__spreadArray([ "export type " + typeName + " =" ], variants.map(function (v) { return "\t| " + typeName + "_" + v.name; })), [ "", ]).join("\n"); }; var generateConstructor = function (typeName, variant) { var fields = __spreadArray([ "\t\t_t: " + typeName + "_" + variant.name + "_Discriminator" ], variant.fields.map(function (v) { return "\t\t" + v.name; })).join(",\n"); return [ "\t" + variant.name + ": (" + generateVariantFields(variant) + "): " + typeName + "_" + variant.name + " => ({", fields, "\t})", ].join("\n"); }; var generateConstructors = function (typeName, variants) { return variants.map(function (v) { return generateConstructor(typeName, v); }).join(",\n"); }; var generateGuards = function (typeName, variants) { return variants .map(function (v) { return "\tis" + v.name + ": (v: any): v is " + typeName + "_" + v.name + " => v !== null && typeof v === \"object\" && \"_t\" in v && v._t === " + typeName + "_" + v.name + "_Discriminator"; }) .join(",\n"); }; var generateConstructorsAndGuards = function (typeName, variants) { return [ "export const " + typeName + " = {", generateConstructors(typeName, variants) + ",", generateGuards(typeName, variants), "}", ].join("\n"); }; var generateType = function (typeName, typeConfig) { var builder = new TypeBuilder(); typeConfig(builder); var variants = builder.variants; return [ generateDiscriminators(typeName, variants), generateVariantTypes(typeName, variants), generateMainType(typeName, variants), generateConstructorsAndGuards(typeName, variants), ].join("\n"); }; exports.generateType = generateType; var generateFile = function (filePath, fileConfig) { var builder = new FileBuilder(); fileConfig(builder); var types = builder.types; var dirName = path.dirname(filePath); fs.mkdirSync(dirName, { recursive: true }); fs.writeFileSync(filePath, types.join("\n\n") + "\n"); }; exports.generateFile = generateFile;