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
JavaScript
;
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;