X typescript generation

We’re looking at using x typescript to generate the dtos for a large project to be used by a Next.JS app.

We found two issues with the generated code:

  • several classes on our service models and DTOs that have the same name on different namespaces. These are mostly
    helper classes or enums named “OrderBy” or FilterBy, and compilation fails due to name colisions.
  • Since it generates a single file, we end up with a single .ts file that is 1Mb in size with about 850 service models. We want to avoid having the client download and parse a single 1Mb file, specially since most of the time each page only needs 1/100 of that file.

To fix both issues, we looked at splitting manually the generated code into separate files.

For each service model we rendered a file with IncludeTypes: <ServiceModel>. This only generates the model and the response. The DTOs are not picked up and the file fails to compile.

What would be the expected solution for us?

I think ideally we’d be able to pull all types and dependant types, and place each type on a separate file with folders based on the namespaces. This solution would solve both issues:

  • the duplicated files issue because types with the same name would be on separate folders)
  • the large file size, since we can leave webpack to bundle files;

Have a look at the different options IncludeTypes supports for its different behaviors.

We recommend grouping Services by Tag where it’s supported by ServiceStack’s built-in UIs and metadata pages and you can Include All Services in a Tag Group with:

/* Options:
IncludeTypes: {web},{mobile}


That helps a bit, but it comes with a couple of disadvantages which make it unworkable.

I tried to go over all service models, generate a single file per model, and use IncludeTypes:.*.
There are some very common dtos which end up being duplicated on almost all those files. Think of something like UserInfoDto, used by any endpoint that returns some user info attached to the result. Using VSCode to auto-import “UserInfoDto” then results in a huge list of options, because that class is exported on all files.

Using tags to group service models can cut down in the number of files, but still results in duplicated classes, with the disadvantage of having to tag all service models.

Either of these two options cause the same problem of duplicated classes on the generated files.

You should be able to use IncludeTypes={tag} along with ExcludeTypes=... to remove common classes that you don’t want included, whilst keeping common types in a separate file.

But really each tag group should be standalone containing all types that a specific client App needs, e.g. IncludeTypes={web} with just the APIs used by your Web App. Request DTOs can belong to multiple tag groups. You only need to tag Request DTOs as it will include all dependent types that it uses.

As for using same type names in different namespaces that’s only supported in .NET languages, otherwise all DTO Names should be unique if you want your APIs called from multiple languages.

Thanks for the pointers.

We ended up renaming the types with the same name, and using a codemod with ts-morph to move all the classes in one file to separate files per class/service model request/response pair.

1 Like