Strapi v4.3 with TypeScript support and Media Library folders is live 🔥

Hi everybody!

Today, we released a new version with two highly awaited features: TypeScript support and Media library folders (find all details in the blog post) :rocket:

We’d like to say a huge THANK YOU to everyone who helped us work on these features and improve them - we hope that they will make your development and content management experience better.

Here’s the Github changelog with the list of all updates of this release.

We’d love to hear what you think about these features - please share your feedback in the thread!

9 Likes

Do you still have plans to enhance TypeScript support? At the current state (v4.6) it still feels quite rudimentary and like an afterthought. Interfaces are missing a lot of properties that are present at runtime, so I have to either create my own interfaces, add as any or add @ts-ignore comments. For instance the ctx is missing type definitions for request, response and state. Also it would be great to have better native support for model schemas in e.g. custom controllers and services.

I have thought about creating issues/PRs for missing type definitions, but this feels like very symptomatic optimizations and also of course I don’t know what you guys are planning internally.

The whole workflow feels like it’s not optimized for TypeScript. If I work on a plugin, I have to run build or develop on order to “push” my changes to the Strapi instance around it.

I hope with Strapi v5 you would consider writing Strapi in TypeScript from the beginning. It would enhance the dev experience immensely.

Is there a place where I could give more examples?

1 Like

HI @GregorSondermeier I think the core team is planning to improve TypeScript support in the near future. I will see if I can find more information this week.

1 Like

Hello Gregor, thanks for your detailed comment!

Do you still have plans to enhance TypeScript support?

We absolutely do! It’s something we have had in our backlog for a long time and we’re finally going to get started very soon.

At the current state (v4.6) it still feels quite rudimentary and like an afterthought. Interfaces are missing a lot of properties that are present at runtime, so I have to either create my own interfaces, add as any or add @ts-ignore comments. For instance the ctx is missing type definitions for request, response and state. Also it would be great to have better native support for model schemas in e.g. custom controllers and services.

You’re right on all the different points you’ve mentionned. And all of them are topics we’re planning to tackle when working on adding TypeScript types support to Strapi.

As a small reminder/context, 4.3 included TypeScript support which included the possibility to create a Strapi project using TypeScript, but it didn’t come with integrated types or anything like that (well except for a small bonus util that served as an experiment for user type generation and that you can run with yarn strapi ts:generate-types --verbose). The main goal was to make it possible to work with TS & Strapi, even if it’s not perfect.

However, we are very well aware that it’s far from enough, both for us as contributors and also for the developers trying to build complex applications based on Strapi.

The future of Strapi x TypeScript will thus focus on that: crafting an awesome developer experience for Strapi developers. In the best scenario, this could include types for the core Strapi APIs, a low-level type system (to work with the very generic data structures we’re used to in Strapi), Auto-generated type definition for user custom code (and schemas), loose generic types to enable customization from plugins, strongly typed content API, etc…

Of course, I won’t promise everything will be available at first. Still, we’ll make our best to couple the endless customization possibilities that Strapi has to offer with the fantastic developer experience that TypeScript can provide.

Our vision here is to incrementally build a smooth developer experience thanks to complex yet powerful Strapi x TS building blocks and then expand from there.

I have thought about creating issues/PRs for missing type definitions, but this feels like very symptomatic optimizations, and also of course I don’t know what you guys are planning internally.

We’ve received a lot of those PRs (and issues) in the year following the initial release of v4.3, but as long as we didn’t have a clear vision of where we wanted to go with TS types within Strapi, we couldn’t guide the contributors nor accepting any of the proposed changes.

Also, as you mentioned, those additions would have been at best very localized and lacked customization/generic capabilities as we didn’t have the groundwork necessary to build complex Strapi types.

The whole workflow feels like it’s not optimized for TypeScript. If I work on a plugin, I have to run build or develop on order to “push” my changes to the Strapi instance around it.

Well, this is actually in the scope of the 4.3 release :eyes:

I’m curious about what you would have imagined as an alternative workflow. (Also keep in mind that plugins are still independent Strapi pieces)

I hope with Strapi v5 you would consider writing Strapi in TypeScript from the beginning. It would enhance the dev experience immensely.

We’re exploring a lot of options and ideas for V5 :slight_smile:

Is there a place where I could give more examples?

We’re going to start crafting RFCs once we start the TypeScript work, I think it’ll be an awesome place to collect feedback and ideas. Stay tuned!

I hope I answered your questions and concerns, and if something isn’t clear, don’t hesitate to say so,

Have a nice day!

3 Likes

Hi @Convly and thanks a lot for the very detailed response!

Let me give you some context as to why I’m still a bit sceptical about Strapi+TypeScript:

I was working as a frontend engineer at my last company. I was part of the team that developed an Angular driven frontend application. TypeScript was famously developed together with Angular IIRC (or at least they were enhanced by and benefited from each other in the early days) so these go very well together. In that frontend application (and in every other clean Angular application), everything is typed. Actually, even the recommended typescript-eslint config warns you that “The any type in TypeScript is a dangerous “escape hatch” from the type system.”.

Now, obviously Strapi has a completely different background, foundation and business case than Angular.

Still, imagine my surprise when I started at my current company and I learned that the CMS backend application (It was Strapi v3.6 back then) is written in pure untyped JavaScript. I couldn’t believe that a backend application, where most business logic should be executed and where stability, predictability and security is king, was written in pure JavaScript. By that alone, the backend is less predictable than the frontend, which IMO is hard to swallow.
And when Strapi v4 was released, there was still not TypeScript support initially. Now it’s 2023 and TS support is still very basic.

Ok, the learning curve for TypeScript might be a bit steeper initially for newcomer developers than it is for JavaScript. And this might actually be one of your motivations to focus on JavaScript first. But I’m convinced that if you want to scale up and be competitive in the long run and be more than just a CMS for blog-like websites, TypeScript is the way to go. Because it enhances the dev experience, it makes your implementation predictable and allows developers to catch bugs before runtime.

Also the code can significantly document itself. I’m pretty active in the forum and on discord and the amount of questions that are based on the fact that the state of variables and objects are unclear, or which functions are available at which point, are mindblowing.

Now let my try to respond to some of the points your mentioned :slight_smile:

to work with the very generic data structures we’re used to in Strapi

That’s true, there are some very generic data structures. Also I think this “autodiscover” principle (if a file exists in a certain folder and has a certain name, it has a certain meaning) is a bit weird. Without knowing exactly a possible alternative solution, I feel like Generics and Decorators (ES, TS, ng) could be very helpful.
Also the global almighty strapi object feels problematic right now. There are properties that are not documented, but even the documented stuff behaves unpredictable. There is no guarantee that strapi.service('api::restaurant.restaurant') returns something and that something is the restaurant service. Let alone my IDE can suggest to me which functions the restaurant service has. It feels pretty 2010 and earlier when this exact problem existed in JS driven frontends.

As a small reminder/context, 4.3 included TypeScript support

You know what, actually I might have misunderstood and overestimated what exactly this means. Thanks to your clarification I know now, but for the reasons mentioned above I’m not sure what real value it brings at this state.

Well, this is actually in the scope of the 4.3 release :eyes:

I’m curious about what you would have imagined as an alternative workflow. (Also keep in mind that plugins are still independent Strapi pieces)

When I add a local plugin to my TypeScript driven Strapi project, I have to have a second terminal open and run npm run develop in there so that my TS plugin gets transpiled to JS. Because my Strapi project, despite being written in TS, only recognized the transpiled plugin in the dist folder. This feels awkward and has repeatedly led to confusion by discord users.

I haven’t tried the following yet, but I wonder how this would work when I want to publish a plugin written in TS on npm or the Strapi marketplace. It has to be compatible with JS Strapi projects. I guess I’d have to publish only the dist folder then, and maybe some types, but not the actual TS implementation.

We’re exploring a lot of options and ideas for V5 :slight_smile:

I’m very curious about the future of Strapi, because as much as I hated it in the beginning for all its unpredictabilities (sorry I’m just being honest), I started to really like it in the recent weeks. Because at the very foundation, I find it very easy to quickly create some schemas and have a content API with little to no implementation. But then again, I’m not sure about the scalability with the current architecture.

We’re going to start crafting RFCs once we start the TypeScript work, I think it’ll be an awesome place to collect feedback and ideas. Stay tuned!

Count me in to contribute if I can and may :smiley:

Have a nice day!

And have a nice day yourself! :slight_smile:

3 Likes

This is the main issue I’m having with Strapi at the moment. It feels like the benefits of having the entityService is lost. I was also disappointed when I realised that this is what typescript “support” meant.

I’m stuck with Strapi but I need to evaluate if moving away from Strapis built ins and using something like Prisma directly is a better option

1 Like

Hey @GregorSondermeier, I’ve to admit I forgot about this thread until today.

We’ve actually started rolling out some improvements to our TypeScript support and are in the process of iteratively building types for Strapi APIs (including the entity service or the core factories) which we will be releasing over the next few months.

You can find the PR that contains the foundation of our new TypeScript system here

Again, I’m sorry it took this long to ping you but I hope you’ll be as excited as we’re about the future of Strapi x TS :slightly_smiling_face:

Have a nice day!

Seeing very slow compilation times when using typescript. I’m seeing that in typescript-utils/lib/ compile.js takes solid 20s+ to compile. Is there a way we can speed this up? May be use bun or swc or something else?

That’s something we could look into. We could also get better results just by improving the incremental builds.

Could you please open an issue on GitHub with more information regarding this?

I just wrote an article on some patching I did to speed up development times. Essentially I just swapped out the default compiler with SWC. May be we could make this the default compiler?