mrjono1 / joi-to-typescript

Convert Joi Schemas to TypeScript interfaces
MIT License
126 stars 40 forks source link

Option to generate readonly types from Joi schemas #254

Closed samhwang closed 1 year ago

samhwang commented 2 years ago

Hey @mrjono1, really love the work you do on this project!

I'm just asking is there a way to add a option in the command to make the generated interfaces have readonly attributes? I'd say this is a good thing because enforcing immutability is a good thing in some cases. Probably an option like generateReadonlyAttributes: true ?

Example of this could be:

const userSchema = joi.object({
  name: joi.string().required(),
}).meta({ className: 'User' });

// Generated interface
interface User {
  readonly name: string;
}
mrjono1 commented 2 years ago

We can think of a way to do this

mrjono1 commented 2 years ago

Maybe meta a tag:

const userSchema = joi.object({
  name: joi.string().required().meta({readonly:true})
}).meta({ className: 'User' });

// Generated interface
interface User {
  readonly name: string;
}

This pattern i could also do public, private, protected properties

samhwang commented 2 years ago

Only problem I can see with that is interface properties/type members don't have public, private or protected haha. But I agree putting a meta readonly is great.

mrjono1 commented 2 years ago

Lol yep, i should have looked harder im on my phone

francescosalvi commented 1 year ago

In case anybody is in need of a quick/dirty workaround, here is a patch for current version 4.0.7 that enforces readonly for all props and arrays:

diff --git a/node_modules/joi-to-typescript/dist/main/parse.js b/node_modules/joi-to-typescript/dist/main/parse.js
index 7db1eca..8a7831e 100644
--- a/node_modules/joi-to-typescript/dist/main/parse.js
+++ b/node_modules/joi-to-typescript/dist/main/parse.js
@@ -87,8 +87,8 @@ function typeContentToTsHelper(settings, parsedSchema, indentLevel, doExport = f
             const arrayStr = settings.supplyDefaultsInType
                 ? parsedSchema.value !== undefined
                     ? `${wrapValue(parsedSchema.value)} | ${content}`
-                    : `${content}[]`
-                : `${content}[]`;
+                    : `readonly ${content}[]`
+                : `readonly ${content}[]`;
             if (doExport) {
                 return {
                     tsContent: `export type ${parsedSchema.interfaceOrTypeName} = ${arrayStr};`,
@@ -126,7 +126,7 @@ function typeContentToTsHelper(settings, parsedSchema, indentLevel, doExport = f
                     const descriptionStr = (0, write_1.getJsDocString)(settings, child.interfaceOrTypeName, childInfo.jsDoc, indentLevel);
                     const optionalStr = child.required ? '' : '?';
                     const indentString = (0, write_1.getIndentStr)(settings, indentLevel);
-                    return `${descriptionStr}${indentString}${child.interfaceOrTypeName}${optionalStr}: ${childInfo.tsContent};`;
+                    return `${descriptionStr}${indentString}readonly ${child.interfaceOrTypeName}${optionalStr}: ${childInfo.tsContent};`;
                 });
                 objectStr = `{\n${childrenContent.join('\n')}\n${(0, write_1.getIndentStr)(settings, indentLevel - 1)}}`;
                 if (parsedSchema.value !== undefined && settings.supplyDefaultsInType) {
diff --git a/node_modules/joi-to-typescript/dist/module/parse.js b/node_modules/joi-to-typescript/dist/module/parse.js
index f565c0b..c775346 100644
--- a/node_modules/joi-to-typescript/dist/module/parse.js
+++ b/node_modules/joi-to-typescript/dist/module/parse.js
@@ -83,8 +83,8 @@ function typeContentToTsHelper(settings, parsedSchema, indentLevel, doExport = f
             const arrayStr = settings.supplyDefaultsInType
                 ? parsedSchema.value !== undefined
                     ? `${wrapValue(parsedSchema.value)} | ${content}`
-                    : `${content}[]`
-                : `${content}[]`;
+                    : `readonly ${content}[]`
+                : `readonly ${content}[]`;
             if (doExport) {
                 return {
                     tsContent: `export type ${parsedSchema.interfaceOrTypeName} = ${arrayStr};`,
@@ -122,7 +122,7 @@ function typeContentToTsHelper(settings, parsedSchema, indentLevel, doExport = f
                     const descriptionStr = getJsDocString(settings, child.interfaceOrTypeName, childInfo.jsDoc, indentLevel);
                     const optionalStr = child.required ? '' : '?';
                     const indentString = getIndentStr(settings, indentLevel);
-                    return `${descriptionStr}${indentString}${child.interfaceOrTypeName}${optionalStr}: ${childInfo.tsContent};`;
+                    return `${descriptionStr}${indentString}readonly ${child.interfaceOrTypeName}${optionalStr}: ${childInfo.tsContent};`;
                 });
                 objectStr = `{\n${childrenContent.join('\n')}\n${getIndentStr(settings, indentLevel - 1)}}`;
                 if (parsedSchema.value !== undefined && settings.supplyDefaultsInType) {
mrjono1 commented 1 year ago

https://github.com/mrjono1/joi-to-typescript/pull/319

mrjono1 commented 1 year ago

Feature added and released under 4.2.0